/
error.go
112 lines (98 loc) · 3.17 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
package igdb
import (
"encoding/json"
"github.com/pkg/errors"
"io/ioutil"
"log"
"net/http"
"strconv"
)
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",
}
// 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",
}
// 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",
}
// ErrInternalError occurs when an unexpected IGDB server error occurs and should be reported.
ErrInternalError = ServerError{
Status: http.StatusInternalServerError,
Msg: "internal error: report bug",
}
)
// ServerError contains information on an
// error returned from an IGDB API call.
type ServerError struct {
Status int `json:"status"`
Msg string `json:"message"`
}
// 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
}
// 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
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
log.Println(string(b))
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
}