github.com/abemedia/go-don@v0.2.2-0.20240329015135-be88e32bb73b/errors.go (about) 1 package don 2 3 import ( 4 "bytes" 5 "context" 6 "encoding" 7 "encoding/xml" 8 "errors" 9 "strconv" 10 11 "github.com/abemedia/go-don/internal/byteconv" 12 "github.com/goccy/go-json" 13 "github.com/valyala/fasthttp" 14 "gopkg.in/yaml.v3" 15 ) 16 17 func E(err error) fasthttp.RequestHandler { 18 h := H(func(context.Context, any) (any, error) { return nil, err }) 19 return func(ctx *fasthttp.RequestCtx) { h(ctx, nil) } 20 } 21 22 type HTTPError struct { 23 err error 24 code int 25 } 26 27 func Error(err error, code int) *HTTPError { 28 return &HTTPError{err, code} 29 } 30 31 func (e *HTTPError) Error() string { 32 return e.err.Error() 33 } 34 35 func (e *HTTPError) Is(err error) bool { 36 return errors.Is(e.err, err) || errors.Is(StatusError(e.code), err) 37 } 38 39 func (e *HTTPError) Unwrap() error { 40 return e.err 41 } 42 43 func (e *HTTPError) StatusCode() int { 44 if e.code != 0 { 45 return e.code 46 } 47 48 var sc StatusCoder 49 if errors.As(e.err, &sc) { 50 return sc.StatusCode() 51 } 52 53 return fasthttp.StatusInternalServerError 54 } 55 56 func (e *HTTPError) MarshalText() ([]byte, error) { 57 var m encoding.TextMarshaler 58 if errors.As(e.err, &m) { 59 return m.MarshalText() 60 } 61 62 return byteconv.Atob(e.Error()), nil 63 } 64 65 func (e *HTTPError) MarshalJSON() ([]byte, error) { 66 var m json.Marshaler 67 if errors.As(e.err, &m) { 68 return m.MarshalJSON() 69 } 70 71 var buf bytes.Buffer 72 buf.WriteString(`{"message":`) 73 buf.WriteString(strconv.Quote(e.Error())) 74 buf.WriteRune('}') 75 76 return buf.Bytes(), nil 77 } 78 79 func (e *HTTPError) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { 80 var m xml.Marshaler 81 if errors.As(e.err, &m) { 82 return m.MarshalXML(enc, start) 83 } 84 85 start = xml.StartElement{Name: xml.Name{Local: "message"}} 86 return enc.EncodeElement(e.Error(), start) 87 } 88 89 func (e *HTTPError) MarshalYAML() (any, error) { 90 var m yaml.Marshaler 91 if errors.As(e.err, &m) { 92 return m.MarshalYAML() 93 } 94 95 return map[string]string{"message": e.Error()}, nil 96 } 97 98 var ( 99 _ error = (*HTTPError)(nil) 100 _ encoding.TextMarshaler = (*HTTPError)(nil) 101 _ json.Marshaler = (*HTTPError)(nil) 102 _ xml.Marshaler = (*HTTPError)(nil) 103 _ yaml.Marshaler = (*HTTPError)(nil) 104 ) 105 106 // StatusError creates an error from an HTTP status code. 107 type StatusError int 108 109 const ( 110 ErrBadRequest = StatusError(fasthttp.StatusBadRequest) 111 ErrUnauthorized = StatusError(fasthttp.StatusUnauthorized) 112 ErrForbidden = StatusError(fasthttp.StatusForbidden) 113 ErrNotFound = StatusError(fasthttp.StatusNotFound) 114 ErrMethodNotAllowed = StatusError(fasthttp.StatusMethodNotAllowed) 115 ErrNotAcceptable = StatusError(fasthttp.StatusNotAcceptable) 116 ErrConflict = StatusError(fasthttp.StatusConflict) 117 ErrUnsupportedMediaType = StatusError(fasthttp.StatusUnsupportedMediaType) 118 ErrInternalServerError = StatusError(fasthttp.StatusInternalServerError) 119 ) 120 121 func (e StatusError) Error() string { 122 return fasthttp.StatusMessage(int(e)) 123 } 124 125 func (e StatusError) StatusCode() int { 126 return int(e) 127 }