-
Notifications
You must be signed in to change notification settings - Fork 1
/
herrors.go
132 lines (112 loc) · 3.99 KB
/
herrors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package herrors
import (
"errors"
"net/http"
)
var (
// 4xx errors
ErrBadRequest = New(http.StatusBadRequest)
ErrUnauthorized = New(http.StatusUnauthorized)
ErrPaymentRequired = New(http.StatusPaymentRequired)
ErrForbidden = New(http.StatusForbidden)
ErrNotFound = New(http.StatusNotFound)
ErrMethodNotAllowed = New(http.StatusMethodNotAllowed)
ErrNotAcceptable = New(http.StatusNotAcceptable)
ErrProxyAuthRequired = New(http.StatusProxyAuthRequired)
ErrRequestTimeout = New(http.StatusRequestTimeout)
ErrConflict = New(http.StatusConflict)
ErrResourceGone = New(http.StatusGone)
ErrLengthRequired = New(http.StatusLengthRequired)
ErrPreconditionFailed = New(http.StatusPreconditionFailed)
ErrEntityTooLarge = New(http.StatusRequestEntityTooLarge)
ErrURITooLong = New(http.StatusRequestURITooLong)
ErrUnsupportedMediaType = New(http.StatusUnsupportedMediaType)
ErrRangeNotSatisfiable = New(http.StatusRequestedRangeNotSatisfiable)
ErrExpectationFailed = New(http.StatusExpectationFailed)
ErrMisdirectedRequest = New(http.StatusMisdirectedRequest)
ErrUnprocessableEntity = New(http.StatusUnprocessableEntity)
ErrLocked = New(http.StatusLocked)
ErrFailedDependency = New(http.StatusFailedDependency)
ErrTooEarly = New(http.StatusTooEarly)
ErrPreconditionRequired = New(http.StatusPreconditionRequired)
ErrTooManyRequests = New(http.StatusTooManyRequests)
ErrHeaderFieldsTooLarge = New(http.StatusRequestHeaderFieldsTooLarge)
ErrIllegal = New(http.StatusUnavailableForLegalReasons)
// 5xx errors
ErrInternalServer = New(http.StatusInternalServerError)
ErrNotImplemented = New(http.StatusNotImplemented)
ErrBadGateway = New(http.StatusBadGateway)
ErrServiceUnavailable = New(http.StatusServiceUnavailable)
ErrGatewayTimeout = New(http.StatusGatewayTimeout)
ErrHTTPVersionNotSupported = New(http.StatusHTTPVersionNotSupported)
ErrVariantAlsoNegotiates = New(http.StatusVariantAlsoNegotiates)
ErrInsufficientStorage = New(http.StatusInsufficientStorage)
ErrLoopDetected = New(http.StatusLoopDetected)
ErrNotExtended = New(http.StatusNotExtended)
ErrNetworkAuthenticationRequired = New(http.StatusNetworkAuthenticationRequired)
)
// New constructs an ErrHttp error with the code and message populated
func New(statusCode uint) error {
e := &ErrHttp{
code: statusCode,
}
e.msg = http.StatusText(int(e.Code()))
return e
}
// Wrap will create a new ErrHttp and place the provided error
// inside of it. There is a complementary errors.Unwrap to retrieve
// the wrapped error.
func Wrap(err error, statusCode uint) error {
e := &ErrHttp{
code: statusCode,
cause: err,
}
e.msg = http.StatusText(int(e.Code()))
return e
}
// Write sets the response status code to the provided
// error code. When unable to find an ErrHttp error in
// the error chain then a 500 internal error is output.
func Write(w http.ResponseWriter, err error) {
if err == nil {
return
}
var target hasCode
// don't allow unknown errors to surface to user
if !errors.As(err, &target) {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(int(target.Code()))
}
type ErrHttp struct {
msg string
code uint
cause error
}
// Code returns http status code that the error represents
func (e *ErrHttp) Code() uint {
if e.code == 0 {
return http.StatusInternalServerError
}
return e.code
}
// Error returns http friendly error message
func (e *ErrHttp) Error() string {
return e.msg
}
// Unwrap will return the first wrapped error if there is one
func (e *ErrHttp) Unwrap() error {
return e.cause
}
// Is used by errors.Is for comparing ErrHttp
func (e *ErrHttp) Is(target error) bool {
h, ok := target.(hasCode)
if !ok {
return false
}
return e.Code() == h.Code()
}
type hasCode interface {
Code() uint
}