go-micro.dev/v5@v5.12.0/errors/errors.go (about) 1 // Package errors provides a way to return detailed information 2 // for an RPC request error. The error is normally JSON encoded. 3 package errors 4 5 import ( 6 "encoding/json" 7 "errors" 8 "fmt" 9 "net/http" 10 ) 11 12 //go:generate protoc -I. --go_out=paths=source_relative:. errors.proto 13 14 func (e *Error) Error() string { 15 b, _ := json.Marshal(e) 16 return string(b) 17 } 18 19 // New generates a custom error. 20 func New(id, detail string, code int32) error { 21 return &Error{ 22 Id: id, 23 Code: code, 24 Detail: detail, 25 Status: http.StatusText(int(code)), 26 } 27 } 28 29 // Parse tries to parse a JSON string into an error. If that 30 // fails, it will set the given string as the error detail. 31 func Parse(err string) *Error { 32 e := new(Error) 33 errr := json.Unmarshal([]byte(err), e) 34 if errr != nil { 35 e.Detail = err 36 } 37 return e 38 } 39 40 func newError(id string, code int32, detail string, a ...interface{}) error { 41 if len(a) > 0 { 42 detail = fmt.Sprintf(detail, a...) 43 } 44 return &Error{ 45 Id: id, 46 Code: code, 47 Detail: detail, 48 Status: http.StatusText(int(code)), 49 } 50 } 51 52 // BadRequest generates a 400 error. 53 func BadRequest(id, format string, a ...interface{}) error { 54 return newError(id, 400, format, a...) 55 } 56 57 // Unauthorized generates a 401 error. 58 func Unauthorized(id, format string, a ...interface{}) error { 59 return newError(id, 401, format, a...) 60 } 61 62 // Forbidden generates a 403 error. 63 func Forbidden(id, format string, a ...interface{}) error { 64 return newError(id, 403, format, a...) 65 } 66 67 // NotFound generates a 404 error. 68 func NotFound(id, format string, a ...interface{}) error { 69 return newError(id, 404, format, a...) 70 } 71 72 // MethodNotAllowed generates a 405 error. 73 func MethodNotAllowed(id, format string, a ...interface{}) error { 74 return newError(id, 405, format, a...) 75 } 76 77 // Timeout generates a 408 error. 78 func Timeout(id, format string, a ...interface{}) error { 79 return newError(id, 408, format, a...) 80 } 81 82 // Conflict generates a 409 error. 83 func Conflict(id, format string, a ...interface{}) error { 84 return newError(id, 409, format, a...) 85 } 86 87 // InternalServerError generates a 500 error. 88 func InternalServerError(id, format string, a ...interface{}) error { 89 return newError(id, 500, format, a...) 90 } 91 92 // Equal tries to compare errors. 93 func Equal(err1 error, err2 error) bool { 94 verr1, ok1 := err1.(*Error) 95 verr2, ok2 := err2.(*Error) 96 97 if ok1 != ok2 { 98 return false 99 } 100 101 if !ok1 { 102 return err1 == err2 103 } 104 105 if verr1.Code != verr2.Code { 106 return false 107 } 108 109 return true 110 } 111 112 // FromError try to convert go error to *Error. 113 func FromError(err error) *Error { 114 if err == nil { 115 return nil 116 } 117 if verr, ok := err.(*Error); ok && verr != nil { 118 return verr 119 } 120 121 return Parse(err.Error()) 122 } 123 124 // As finds the first error in err's chain that matches *Error. 125 func As(err error) (*Error, bool) { 126 if err == nil { 127 return nil, false 128 } 129 var merr *Error 130 if errors.As(err, &merr) { 131 return merr, true 132 } 133 return nil, false 134 } 135 136 func NewMultiError() *MultiError { 137 return &MultiError{ 138 Errors: make([]*Error, 0), 139 } 140 } 141 142 func (e *MultiError) Append(err ...*Error) { 143 e.Errors = append(e.Errors, err...) 144 } 145 146 func (e *MultiError) HasErrors() bool { 147 return len(e.Errors) > 0 148 } 149 150 func (e *MultiError) Error() string { 151 b, _ := json.Marshal(e) 152 return string(b) 153 }