-
Notifications
You must be signed in to change notification settings - Fork 16
/
error.go
158 lines (130 loc) · 3.99 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
/* This file contains helpers to check whether given error
is specific http status code or not.
*/
package profitbricks
import (
"errors"
"fmt"
"net/http"
)
const (
SnapshotInUseErrorCode = "200"
)
type ClientErrorType int
const (
RequestFailed ClientErrorType = iota
UnexpectedResponse
HttpClientError
InvalidInput
)
type ClientError struct {
errType ClientErrorType
msg string
}
func (c ClientError) Error() string {
return c.msg
}
func NewClientError(errType ClientErrorType, msg string) ClientError {
return ClientError{
errType: errType,
msg: msg,
}
}
func IsClientErrorType(err error, errType ClientErrorType) bool {
var clientErr ClientError
if errors.As(err, &clientErr) {
return clientErr.errType == errType
}
return false
}
func IsHttpStatus(err error, status int) bool {
var apiErr ApiError
if errors.As(err, &apiErr) {
return apiErr.HttpStatusCode() == status
}
return false
}
// IsStatusOK - (200)
func IsStatusOK(err error) bool {
return IsHttpStatus(err, http.StatusOK)
}
// IsStatusAccepted - (202) Used for asynchronous requests using PUT, DELETE, POST and PATCH methods.
// The response will also include a Location header pointing to a resource. This can be used for polling.
func IsStatusAccepted(err error) bool {
return IsHttpStatus(err, http.StatusAccepted)
}
// IsStatusNotModified - (304) Response for GETs on resources that have not been changed. (based on ETag values).
func IsStatusNotModified(err error) bool {
return IsHttpStatus(err, http.StatusNotModified)
}
// IsStatusBadRequest - (400) Response to malformed requests or general client errors.
func IsStatusBadRequest(err error) bool {
return IsHttpStatus(err, http.StatusBadRequest)
}
// IsStatusUnauthorized - (401) Response to an unauthenticated connection.
// You will need to use your API username and password to be authenticated.
func IsStatusUnauthorized(err error) bool {
return IsHttpStatus(err, http.StatusUnauthorized)
}
// IsStatusForbidden - (403) Forbidden
func IsStatusForbidden(err error) bool {
return IsHttpStatus(err, http.StatusForbidden)
}
// IsStatusNotFound - (404) if resource does not exist
func IsStatusNotFound(err error) bool {
return IsHttpStatus(err, http.StatusNotFound)
}
// IsStatusMethodNotAllowed - (405) Use for any POST, PUT, PATCH, or DELETE performed
// on read-only resources. This is also the response to PATCH requests
// on resources that do not support partial updates.
func IsStatusMethodNotAllowed(err error) bool {
return IsHttpStatus(err, http.StatusMethodNotAllowed)
}
// IsStatusUnsupportedMediaType - (415) The content-type is incorrect for the payload.
func IsStatusUnsupportedMediaType(err error) bool {
return IsHttpStatus(err, http.StatusUnsupportedMediaType)
}
// IsStatusUnprocessableEntity - (422) Validation errors.
func IsStatusUnprocessableEntity(err error) bool {
return IsHttpStatus(err, http.StatusUnprocessableEntity)
}
// IsStatusTooManyRequests - (429) The number of requests exceeds the rate limit.
func IsStatusTooManyRequests(err error) bool {
return IsHttpStatus(err, http.StatusTooManyRequests)
}
// IsRequestFailed - returns true if the error reason was that the request status was failed
func IsRequestFailed(err error) bool {
return IsClientErrorType(err, RequestFailed)
}
type ApiError struct {
HTTPStatus int `json:"httpStatus"`
Messages []struct {
ErrorCode string `json:"errorCode"`
Message string `json:"message"`
} `json:"messages"`
RawBody []byte
}
func (e ApiError) Error() string {
return e.String()
}
func (e ApiError) String() string {
toReturn := fmt.Sprintf("HTTP Status: %d\nError Messages:", e.HTTPStatus)
for _, m := range e.Messages {
toReturn = toReturn + fmt.Sprintf("Error Code: %s Message: %s\n", m.ErrorCode, m.Message)
}
return toReturn
}
func (e ApiError) HttpStatusCode() int {
return e.HTTPStatus
}
func (e ApiError) Body() []byte {
return e.RawBody
}
func (e ApiError) HasErrorCode(code string) bool {
for _, m := range e.Messages {
if m.ErrorCode == code {
return true
}
}
return false
}