Repository navigation
Expand file tree
/
Copy patherrors.go
More file actions
132 lines (115 loc) · 3.12 KB
/
Copy patherrors.go
File metadata and controls
132 lines (115 loc) · 3.12 KB
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 asana
import (
"errors"
"fmt"
"net/http"
"strconv"
"time"
"github.com/rs/xid"
)
func (r *Response) Error(resp *http.Response, requestID xid.ID) error {
var asanaError *Error
if r.Errors != nil {
asanaError = r.Errors[0].withType(resp.StatusCode, resp.Status)
} else {
asanaError = &Error{
StatusCode: resp.StatusCode,
Type: resp.Status,
Message: "Unknown error",
RequestID: requestID.String(),
}
}
retryHeader := resp.Header.Get("Retry-After")
if retryHeader != "" {
retryAfter, err := strconv.ParseInt(retryHeader, 10, 64)
if err == nil {
asanaError.RetryAfter = time.Duration(retryAfter) * time.Second
}
}
return asanaError
}
// Error is an error message returned by the API
type Error struct {
StatusCode int
Type string
Message string `json:"message"`
Phrase string `json:"phrase"`
Help string `json:"help"`
RetryAfter time.Duration `json:"-"`
RequestID string `json:"-"`
}
func (err Error) Error() string {
return fmt.Sprintf("%s %d: %s", err.RequestID, err.StatusCode, err.Message)
}
func IsAsanaError(err error) (*Error, bool) {
var e *Error
if errors.As(err, &e) {
return e, true
}
return nil, false
}
func (err *Error) withType(statusCode int, errorType string) *Error {
err.StatusCode = statusCode
err.Type = errorType
return err
}
func IsRecoverableError(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode/100 == 5
}
return false
}
func IsFatalError(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode/100 != 5
}
return false
}
// IsNotFoundError checks if the provided error represents a 404 not found response from the API
func IsNotFoundError(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode == 404
}
return false
}
// IsAuthError checks if the provided error represents a 401 Authorization error response from the API
func IsAuthError(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode == 401
}
return false
}
// IsPaymentRequired checks if the provided error represents a 402 Payment
// Required response from the API. Asana returns this when the request needs a
// feature that the workspace's plan, or the user's membership, does not
// include, such as custom fields for free workspaces or guests.
func IsPaymentRequired(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode == 402
}
return false
}
// IsRateLimited returns true if the error was a rate limit error
func IsRateLimited(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode == 429
}
return false
}
// IsRateLimited returns true if the error was a rate limit error
func IsPayloadTooLarge(err error) bool {
if e, ok := IsAsanaError(err); ok {
return e.StatusCode == 413
}
return false
}
// RetryAfter returns a Duration indicating after how many seconds a rate-limited requests may be retried
// or nil if the error was not a rate limit error
func RetryAfter(err error) time.Duration {
if e, ok := IsAsanaError(err); ok {
if e.StatusCode == 429 {
return e.RetryAfter
}
}
return time.Minute
}