-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy patherror.go
90 lines (77 loc) · 2.29 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
package sheets
import (
"fmt"
"io/ioutil"
"net/http"
)
// ResourceError is a Client type error.
// It returns from Client's method when server replies with an error.
// It holds the HTTP Method, URL, Status Code and the actual error message came from server.
//
// See `IsResourceError` and `IsStatusError` too.
type ResourceError struct {
Method string
URL string
StatusCode int
Message string
}
func newResourceError(resp *http.Response) *ResourceError {
cause := "unspecified"
if resp.Body != nil {
b, err := ioutil.ReadAll(resp.Body)
if err == nil {
cause = string(b)
}
}
endpoint := resp.Request.URL.String()
return &ResourceError{
Method: resp.Request.Method,
URL: endpoint,
StatusCode: resp.StatusCode,
Message: cause,
}
}
// Error implements a Go error and returns a human-readable error text.
func (e *ResourceError) Error() string {
return fmt.Sprintf("resource error [%s: %s]: %d: %s", e.Method, e.URL, e.StatusCode, e.Message)
}
// IsStatusError reports whether a "target" error is type of `ResourceError` and the status code is the provided "statusCode" one.
// Usage:
// resErr, ok := IsStatusError(http.StatusNotFound, err)
//
// if ok {
// [ressErr.Method, URL, StatusCode, Message...]
// }
//
// See `IsResourceError` too.
func IsStatusError(statusCode int, target error) (*ResourceError, bool) {
if target == nil {
return nil, false
}
t, ok := target.(*ResourceError)
if !ok {
return nil, false
}
return t, t.StatusCode == statusCode
}
// IsResourceError reports whether "target" is "e" ResourceError.
// Returns true when all fields of "e" are equal to "target" fields
// or when a "target" matching field is empty.
func IsResourceError(e *ResourceError, target error) bool {
if target == nil {
return e == nil
}
t, ok := target.(*ResourceError)
if !ok {
return false
}
return (e.Method == t.Method || t.Method == "") &&
(e.URL == t.URL || t.URL == "") &&
(e.StatusCode == t.StatusCode || t.StatusCode <= 0) &&
(e.Message == t.Message || t.Message == "")
}
// Is implements the standard`errors.Is` internal interface.
// It's equivalent of the `IsResourceError` package-level function.
func (e *ResourceError) Is(target error) bool { // implements Go 1.13 errors.Is internal interface.
return IsResourceError(e, target)
}