-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy patherror.go
130 lines (114 loc) · 3.66 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
package igdb
import (
"encoding/json"
"io/ioutil"
"net/http"
"strconv"
"github.com/pkg/errors"
)
var (
// ErrNegativeID occurs when a negative ID is used as an argument in an API call.
ErrNegativeID = errors.New("ID cannot be negative")
// ErrEmptyIDs occurs when a List function is called without a populated int slice.
ErrEmptyIDs = errors.New("IDs argument empty")
// ErrNoResults occurs when the IGDB returns an empty array, void of results.
ErrNoResults = errors.New("results are empty")
// errInvalidJSON occurs when encountering an unexpected end of JSON input.
errInvalidJSON = errors.New("invalid JSON")
)
// Errors returned when encountering error status codes.
var (
// ErrBadRequest occurs when a request is malformed.
ErrBadRequest = ServerError{
Status: http.StatusBadRequest,
Msg: "bad request: check query parameters",
Temp: false,
}
// ErrUnauthorized occurs when a request is made without authorization.
ErrUnauthorized = ServerError{
Status: http.StatusUnauthorized,
Msg: "authentication failed: check for valid API key in user-key header",
Temp: false,
}
// ErrForbidden occurs when a request is made without authorization.
ErrForbidden = ServerError{
Status: http.StatusForbidden,
Msg: "authentication failed: check for valid API key in user-key header",
Temp: false,
}
// ErrInternalError occurs when an unexpected IGDB server error occurs and should be reported.
ErrInternalError = ServerError{
Status: http.StatusInternalServerError,
Msg: "internal error: report bug",
Temp: false,
}
// ErrManyRequests occurs when request rate exceeds 4 per second.
// For full information, visit https://api-docs.igdb.com/#rate-limits
ErrManyRequests = ServerError{
Status: http.StatusTooManyRequests,
Msg: "too many requests",
Temp: true,
}
)
// ServerError contains information on an
// error returned from an IGDB API call.
type ServerError struct {
Status int `json:"status"`
Msg string `json:"message"`
Temp bool `json:"temporary"`
}
// Error formats the ServerError and fulfills the error interface.
func (e ServerError) Error() string {
return "igdb server error: status: " + strconv.Itoa(e.Status) + " message: " + e.Msg
}
// Temporary returns true if the error is temporary.
func (e ServerError) Temporary() bool {
return e.Temp
}
// checkResponse checks the provided HTTP response
// for errors returned by the IGDB.
func checkResponse(resp *http.Response) error {
switch resp.StatusCode {
case http.StatusOK:
return nil
case http.StatusBadRequest:
return ErrBadRequest
case http.StatusUnauthorized:
return ErrUnauthorized
case http.StatusForbidden:
return ErrForbidden
case http.StatusInternalServerError:
return ErrInternalError
case http.StatusTooManyRequests:
return ErrManyRequests
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
var e ServerError
err = json.Unmarshal(b, &e)
if err != nil {
return errors.Wrap(err, "could not unmarshal server error message")
}
return e
}
// Byte representations of ASCII characters. Used for empty result checks.
const (
// openBracketASCII represents the ASCII code for an open bracket.
openBracketASCII = 91
// closedBracketASCII represents the ASCII code for a closed bracket.
closedBracketASCII = 93
)
// isBracketPair returns true if the provided slice of bytes is equivalent to
// an open and closed bracket pair in byte representation. Otherwise, false is returned.
// Used primarily to check if the results of an API call are an empty array.
func isBracketPair(b []byte) bool {
if len(b) != 2 {
return false
}
if b[0] == openBracketASCII && b[1] == closedBracketASCII {
return true
}
return false
}