| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- package errcode
- import (
- "fmt"
- "net/http"
- "sort"
- "sync"
- )
- var (
- errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}
- idToDescriptors = map[string]ErrorDescriptor{}
- groupToDescriptors = map[string][]ErrorDescriptor{}
- )
- var (
- // ErrorCodeUnknown is a generic error that can be used as a last
- // resort if there is no situation-specific error message that can be used
- ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
- Value: "UNKNOWN",
- Message: "unknown error",
- Description: `Generic error returned when the error does not have an
- API classification.`,
- HTTPStatusCode: http.StatusInternalServerError,
- })
- // ErrorCodeUnsupported is returned when an operation is not supported.
- ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
- Value: "UNSUPPORTED",
- Message: "The operation is unsupported.",
- Description: `The operation was unsupported due to a missing
- implementation or invalid set of parameters.`,
- HTTPStatusCode: http.StatusMethodNotAllowed,
- })
- // ErrorCodeUnauthorized is returned if a request requires
- // authentication.
- ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
- Value: "UNAUTHORIZED",
- Message: "authentication required",
- Description: `The access controller was unable to authenticate
- the client. Often this will be accompanied by a
- Www-Authenticate HTTP response header indicating how to
- authenticate.`,
- HTTPStatusCode: http.StatusUnauthorized,
- })
- // ErrorCodeDenied is returned if a client does not have sufficient
- // permission to perform an action.
- ErrorCodeDenied = Register("errcode", ErrorDescriptor{
- Value: "DENIED",
- Message: "requested access to the resource is denied",
- Description: `The access controller denied access for the
- operation on a resource.`,
- HTTPStatusCode: http.StatusForbidden,
- })
- // ErrorCodeUnavailable provides a common error to report unavailability
- // of a service or endpoint.
- ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
- Value: "UNAVAILABLE",
- Message: "service unavailable",
- Description: "Returned when a service is not available",
- HTTPStatusCode: http.StatusServiceUnavailable,
- })
- // ErrorCodeTooManyRequests is returned if a client attempts too many
- // times to contact a service endpoint.
- ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{
- Value: "TOOMANYREQUESTS",
- Message: "too many requests",
- Description: `Returned when a client attempts to contact a
- service too many times`,
- HTTPStatusCode: http.StatusTooManyRequests,
- })
- )
- var nextCode = 1000
- var registerLock sync.Mutex
- // Register will make the passed-in error known to the environment and
- // return a new ErrorCode
- func Register(group string, descriptor ErrorDescriptor) ErrorCode {
- registerLock.Lock()
- defer registerLock.Unlock()
- descriptor.Code = ErrorCode(nextCode)
- if _, ok := idToDescriptors[descriptor.Value]; ok {
- panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value))
- }
- if _, ok := errorCodeToDescriptors[descriptor.Code]; ok {
- panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code))
- }
- groupToDescriptors[group] = append(groupToDescriptors[group], descriptor)
- errorCodeToDescriptors[descriptor.Code] = descriptor
- idToDescriptors[descriptor.Value] = descriptor
- nextCode++
- return descriptor.Code
- }
- type byValue []ErrorDescriptor
- func (a byValue) Len() int { return len(a) }
- func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
- func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value }
- // GetGroupNames returns the list of Error group names that are registered
- func GetGroupNames() []string {
- keys := []string{}
- for k := range groupToDescriptors {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- return keys
- }
- // GetErrorCodeGroup returns the named group of error descriptors
- func GetErrorCodeGroup(name string) []ErrorDescriptor {
- desc := groupToDescriptors[name]
- sort.Sort(byValue(desc))
- return desc
- }
- // GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are
- // registered, irrespective of what group they're in
- func GetErrorAllDescriptors() []ErrorDescriptor {
- result := []ErrorDescriptor{}
- for _, group := range GetGroupNames() {
- result = append(result, GetErrorCodeGroup(group)...)
- }
- sort.Sort(byValue(result))
- return result
- }
|