-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy patherror.go
199 lines (154 loc) · 5.04 KB
/
error.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package vertex
import (
"fmt"
"net/http"
"time"
"code.google.com/p/go-uuid/uuid"
"github.com/dvirsky/go-pylog/logging"
)
type internalError struct {
Message string
Code int
}
const (
// The request succeeded
Ok = iota
// General failure
ErrGeneralFailure
// Input validation failed
ErrInvalidRequest
// Missing parameter
ErrMissingParam
// Invalid parameter value
ErrInvalidParam
// The request was denied for auth reasons
ErrUnauthorized
// Insecure access denied
ErrInsecureAccessDenied
// We do not want to server this request, the client should not retry
ErrResourceUnavailable
// Please back off
ErrBackOff
// Some middleware took over the request, and the renderer should not render the response
ErrHijacked
insecureAccessMessage = "Insecure http Access not allowed"
)
// ErrorString converts an error code to a user "friendly" string
func httpError(err error) (re int, rm string) {
if err == nil {
return http.StatusOK, http.StatusText(http.StatusOK)
}
incidentId := uuid.New()
if err != Hijacked {
logging.Error("[%s] Error processing request: %s", incidentId, err)
}
statusFunc := func(i int) (int, string) {
return i, fmt.Sprintf("[%s] %s", incidentId, http.StatusText(i))
}
if e, ok := err.(*internalError); !ok {
return statusFunc(http.StatusInternalServerError)
} else {
switch e.Code {
case Ok:
return http.StatusOK, "OK"
case ErrHijacked:
return http.StatusOK, "Request Hijacked By Handler"
case ErrInvalidRequest:
return statusFunc(http.StatusBadRequest)
case ErrInvalidParam, ErrMissingParam:
return http.StatusBadRequest, e.Message
case ErrUnauthorized:
return statusFunc(http.StatusUnauthorized)
case ErrInsecureAccessDenied:
return statusFunc(http.StatusForbidden)
case ErrResourceUnavailable:
return statusFunc(http.StatusServiceUnavailable)
case ErrBackOff:
return statusFunc(http.StatusServiceUnavailable)
case ErrGeneralFailure:
fallthrough
default:
return statusFunc(http.StatusInternalServerError)
}
}
}
// A special error that should be returned when hijacking a request, taking over response rendering from the renderer
var Hijacked = newErrorCode(ErrHijacked, "Request Hijacked, Do not rendere response")
// IsHijacked inspects an error and checks whether it represents a hijacked response
func IsHijacked(err error) bool {
if err == Hijacked {
return true
}
if e, ok := err.(*internalError); !ok {
return false
} else {
return e.Code == ErrHijacked
}
}
func newErrorCode(code int, msg string) error {
return &internalError{
Message: msg,
Code: code,
}
}
func newErrorfCode(code int, format string, args ...interface{}) error {
return &internalError{
Message: fmt.Sprintf(format, args...),
Code: code,
}
}
// Wrap a normal error object with an internal object
func NewError(err error) error {
if _, ok := err.(*internalError); ok {
return err
} else {
return newErrorCode(ErrGeneralFailure, err.Error())
}
}
//Format a new web error from message
func NewErrorf(format string, args ...interface{}) error {
return &internalError{
Message: fmt.Sprintf(format, args...),
Code: ErrGeneralFailure,
}
}
// Error returns the error message of the underlying error object
func (e *internalError) Error() string {
if e != nil {
return fmt.Sprintf("%s", e.Message)
}
return ""
}
// MissingParamError Returns a formatted error stating that a parameter was missing.
//
// NOTE: The message will be returned to the client directly
func MissingParamError(msg string, args ...interface{}) error {
return newErrorfCode(ErrMissingParam, msg, args...)
}
// InvalidRequest returns an error signifying something went bad reading the request data (not the validation process).
// This in general should not be used by APIs
func InvalidRequestError(msg string, args ...interface{}) error {
return newErrorfCode(ErrInvalidRequest, msg, args...)
}
// InvalidParam returns an error signifying an invalid parameter value.
//
// NOTE: The error string will be returned directly to the client
func InvalidParamError(msg string, args ...interface{}) error {
return newErrorfCode(ErrInvalidParam, msg, args...)
}
// Unauthorized returns an error signifying the request was not authorized, but the client may log-in and retry
func UnauthorizedError(msg string, args ...interface{}) error {
return newErrorfCode(ErrUnauthorized, msg, args...)
}
// InsecureAccessDenied returns an error signifying the client has no access to the requested resource
func InsecureAccessDenied(msg string, args ...interface{}) error {
return newErrorfCode(ErrInsecureAccessDenied, msg, args...)
}
// ResourceUnavailable returns an error meaning we do not want to serve this request, the client should not retry
func ResourceUnavailableError(msg string, args ...interface{}) error {
return newErrorfCode(ErrResourceUnavailable, msg, args...)
}
// BackOff returns a back-off error with a message formatted for the given amount of backoff time
func BackOffError(duration time.Duration) error {
return newErrorfCode(ErrBackOff, fmt.Sprintf("Retry-Seconds: %.02f", duration.Seconds()))
}