-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi_response.go
175 lines (142 loc) · 4.32 KB
/
api_response.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package zulip
import (
"encoding/json"
"fmt"
"net/http"
)
const (
// X-RateLimit-Remaining: The number of additional requests of this type
// that the client can send before exceeding its limit.
XRateLimitRemaining string = "X-RateLimit-Remaining"
// X-RateLimit-Limit: The limit that would be applicable to a client that
// had not made any recent requests of this type. This is useful for
// designing a client's burst behavior so as to avoid ever reaching a
// rate limit.
XRateLimitLimit string = "X-RateLimit-Limit"
// X-RateLimit-Reset: The time at which the client will no longer have any
// rate limits applied to it (and thus could do a burst of
// X-RateLimit-Limit requests).
XRateLimitReset string = "X-RateLimit-Reset"
// ResultSuccess is the string returned in the result field when there is
// a success operation
ResultSuccess string = "success"
// ResultError is the string returned in the result field when there is
// an error
ResultError string = "error"
)
// APIResponse is the interface that wraps the basic methods of an API response.
type APIResponse interface {
SetHTTPCode(httpCode int)
SetHTTPHeaders(headers http.Header)
json.Unmarshaler
json.Marshaler
}
// APIResponseBase is the base struct for all API responses.
type APIResponseBase struct {
httpCode int
httpHeaders http.Header
// msg: an internationalized, human-readable error message string.
msg string
// result: either "error" or "success", which is redundant with the HTTP status code, but is convenient when print debugging.
result string
// code: a machine-readable error string, with a default value of
// "BAD_REQUEST" for general errors.
code string
// allFields: a map of all the fields returned in the response.
allFields map[string]any
}
// HTTPCode returns the HTTP status code of the response.
func (a APIResponseBase) HTTPCode() int {
return a.httpCode
}
// HTTPHeaders returns the HTTP headers of the response.
func (a APIResponseBase) HTTPHeaders() http.Header {
return a.httpHeaders
}
// SetHTTPCode sets the HTTP status code of the response.
func (a *APIResponseBase) SetHTTPCode(code int) {
a.httpCode = code
}
// SetHTTPHeaders sets the HTTP headers of the response.
func (a *APIResponseBase) SetHTTPHeaders(headers http.Header) {
a.httpHeaders = headers.Clone()
}
func (a APIResponseBase) XRateLimitRemaining() string {
return a.httpHeaders.Get(XRateLimitRemaining)
}
func (a APIResponseBase) XRateLimitLimit() string {
return a.httpHeaders.Get(XRateLimitLimit)
}
func (a APIResponseBase) XRateLimitReset() string {
return a.httpHeaders.Get(XRateLimitReset)
}
// Msg returns the human-readable error message string.
func (a APIResponseBase) Msg() string {
return a.msg
}
// Result returns either "error" or "success".
func (a APIResponseBase) Result() string {
return a.result
}
// Code returns a machine-readable error string.
func (a APIResponseBase) Code() string {
return a.code
}
// IsError returns true if the result is an error.
func (a APIResponseBase) IsError() bool {
return a.result == ResultError
}
// IsSuccess returns true if the result is a success.
func (a APIResponseBase) IsSuccess() bool {
return a.result == ResultSuccess
}
// FieldValue returns the value of a field in the response.
func (a APIResponseBase) FieldValue(field string) (any, error) {
if v, found := a.allFields[field]; found {
return v, nil
}
return nil, fmt.Errorf("field '%s' not found in extra response fields", field)
}
// AllFields returns all the fields in the response.
func (a APIResponseBase) AllFields() map[string]any {
return a.allFields
}
func (a *APIResponseBase) UnmarshalJSON(b []byte) error {
if string(b) == "null" || string(b) == `""` {
return nil
}
var (
code string
result string
msg string
allFields map[string]any
)
if err := json.Unmarshal(b, &allFields); err != nil {
return err
}
if v, found := allFields["code"]; found {
if val, ok := v.(string); ok {
code = val
}
}
if v, found := allFields["msg"]; found {
if val, ok := v.(string); ok {
msg = val
}
}
if v, found := allFields["result"]; found {
if val, ok := v.(string); ok {
result = val
}
}
*a = APIResponseBase{
code: code,
msg: msg,
result: result,
allFields: allFields,
}
return nil
}
func (a APIResponseBase) MarshalJSON() ([]byte, error) {
return json.Marshal(a.allFields)
}