add extended error handling
fixes #19 This commit was moved from ipfs/go-ipfs-http-client@8e3552ac1e6ea18ffd5f49918eef578de2b224fb
Steven Allen committed
Jun 11, 2019 at 17:41 UTC
1b81f2ef10c40b5ba5a50ae545a62cc050c11813
1 file changed
+61
-1
client/httpapi/response.go
+61
-1
@@ -13,6 +13,48 @@ import (
13
"os"
14
)
15
16
+// Error codes adapted from go-ipfs-cmds. We should find a better solution.
17
+
18
+// ErrorType signfies a category of errors
19
+type ErrorType uint
20
+
21
+// ErrorTypes convey what category of error ocurred
22
+const (
23
+ // ErrNormal is a normal error. The command failed for some reason that's not a bug.
24
+ ErrNormal ErrorType = iota
25
+ // ErrClient means the client made an invalid request.
26
+ ErrClient
27
+ // ErrImplementation means there's a bug in the implementation.
28
+ ErrImplementation
29
+ // ErrRateLimited is returned when the operation has been rate-limited.
30
+ ErrRateLimited
31
+ // ErrForbidden is returned when the client doesn't have permission to
32
+ // perform the requested operation.
33
+ ErrForbidden
34
+)
35
+
36
+func (e ErrorType) Error() string {
37
+ return e.String()
38
+}
39
+
40
+func (e ErrorType) String() string {
41
+ switch e {
42
+ case ErrNormal:
43
+ return "command failed"
44
+ case ErrClient:
45
+ return "invalid argument"
46
+ case ErrImplementation:
47
+ return "internal error"
48
+ case ErrRateLimited:
49
+ return "rate limited"
50
+ case ErrForbidden:
51
+ return "request forbidden"
52
+ default:
53
+ return "unknown error code"
54
+ }
55
+
56
+}
57
+
58
type trailerReader struct {
59
resp *http.Response
60
}
@@ -77,7 +119,13 @@ func (r *Response) decode(dec interface{}) error {
119
type Error struct {
120
Command string
121
Message string
80
- Code int
122
+ Code ErrorType
123
+}
124
+
125
+// Unwrap returns the base error (an ErrorType). Works with go 1.14 error
126
+// helpers.
127
+func (e *Error) Unwrap() error {
128
+ return e.Code
129
}
130
131
func (e *Error) Error() string {
@@ -133,11 +181,23 @@ func (r *Request) Send(c *http.Client) (*Response, error) {
181
fmt.Fprintf(os.Stderr, "ipfs-shell: warning! response (%d) read error: %s\n", resp.StatusCode, err)
182
}
183
e.Message = string(out)
184
+
185
+ // set special status codes.
186
+ switch resp.StatusCode {
187
+ case http.StatusNotFound, http.StatusBadRequest:
188
+ e.Code = ErrClient
189
+ case http.StatusTooManyRequests:
190
+ e.Code = ErrRateLimited
191
+ case http.StatusForbidden:
192
+ e.Code = ErrForbidden
193
+ }
194
case contentType == "application/json":
195
if err = json.NewDecoder(resp.Body).Decode(e); err != nil {
196
fmt.Fprintf(os.Stderr, "ipfs-shell: warning! response (%d) unmarshall error: %s\n", resp.StatusCode, err)
197
}
198
default:
199
+ // This is a server-side bug (probably).
200
+ e.Code = ErrImplementation
201
fmt.Fprintf(os.Stderr, "ipfs-shell: warning! unhandled response (%d) encoding: %s", resp.StatusCode, contentType)
202
out, err := ioutil.ReadAll(resp.Body)
203
if err != nil {