This repository has been archived by the owner on Feb 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
errors.go
168 lines (136 loc) · 3.55 KB
/
errors.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
package zuora
import (
"fmt"
"net/http"
"strings"
)
type responseError struct {
isTemporary bool
message string
}
func (r responseError) Temporary() bool {
return r.isTemporary
}
func (r responseError) Error() string {
return r.message
}
func isRetryableStatusCode(statusCode int) bool {
return http.StatusRequestTimeout == statusCode ||
http.StatusTooManyRequests == statusCode ||
http.StatusInternalServerError == statusCode ||
http.StatusServiceUnavailable == statusCode
}
//ErrorResponse could happen even when you get a 200 response from Zuora.
//The correct way to parse it, is to look at the Code inside reasons acording to Zuora docs.
type errorResponse struct {
Success bool `json:"success"`
ProcessID string `json:"processId"`
Reasons []struct {
Code int `json:"code"`
Message string `json:"message"`
} `json:"reasons"`
}
const (
//Unknown
unknown = 0
//Permission or access denied
accessDenied = 10
//Authentication failed
authFailed = 11
//Invalid format or value
invalidFormat = 20
//Unknown field in request
unknownField = 21
//Missing required field
requiredField = 22
//Rule restriction
ruleRestriction = 30
//Not found
notFound = 40
//Locking contention
lockingContention = 50
//Internal error
internalError = 60
//Request exceeded limit
requestExceeded = 70
//Malformed request
malformedRequest = 90
//Extension error
extensionError = 99
)
func (e errorResponse) Temporary() bool {
return isRetryableStatusCode(getStatus(e))
}
func (e errorResponse) Error() string {
if len(e.Reasons) == 0 {
return "there was an error on Zuora response but reasons array was empty."
}
allMessages := []string{}
for i := 0; i < len(e.Reasons); i++ {
currentCode := e.Reasons[i].Code
currentMessage := e.Reasons[i].Message
allMessages = append(allMessages, fmt.Sprintf("reason %v. Code: %v. Message: %v", i, currentCode, currentMessage))
}
return fmt.Sprintf("all errors from reasons: %v", strings.Join(allMessages, " -- "))
}
func getStatus(e errorResponse) int {
if len(e.Reasons) == 0 {
return http.StatusBadRequest
}
allCodes := []int{}
for i := 0; i < len(e.Reasons); i++ {
currentCode := e.Reasons[i].Code
category := currentCode % 100
allCodes = append(allCodes, category)
}
var isRequestExceeded bool
var isAccessDenied bool
var isAuthDenied bool
var isNotFound bool
var isStatusLocked bool
var isInternalServerError bool
for i := 0; i < len(allCodes); i++ {
currentCode := allCodes[i]
switch currentCode {
case requestExceeded:
isRequestExceeded = true
case accessDenied:
isAccessDenied = true
case authFailed:
isAuthDenied = true
case notFound:
isNotFound = true
case lockingContention:
isStatusLocked = true
case internalError:
isInternalServerError = true
}
}
if isRequestExceeded {
return http.StatusTooManyRequests
} else if isAuthDenied {
return http.StatusUnauthorized
} else if isAccessDenied {
return http.StatusForbidden
} else if isNotFound {
return http.StatusNotFound
} else if isStatusLocked {
return http.StatusLocked
} else if isInternalServerError {
return http.StatusInternalServerError
}
return http.StatusBadRequest
}
type tokenError struct {
Timestamp string `json:"timestamp"`
Status int `json:"status"`
Message string `json:"message"`
Path string `json:"path"`
Reason string `json:"reason"`
}
func (r tokenError) Temporary() bool {
return false
}
func (r tokenError) Error() string {
return fmt.Sprintf("could not generate token: %v - %v - %v - %v", r.Path, r.Reason, r.Status, r.Message)
}