r.go
· 1.7 KiB · Go
Sin formato
func Fetch(
sfo *state.StateFetchOptions,
efo ExtraFetchOptions,
opts FetchOptions,
) (*ClientResponse, error) {
for {
var headers = map[string]string{}
if !efo.NoExtraHeaders {
headers["Content-Type"] = "application/json"
}
if len(efo.Headers) > 0 {
for k, v := range efo.Headers {
headers[k] = v
}
}
if efo.Session != nil {
sess, err := efo.Session.GetCurrentSession()
if err != nil {
return nil, err
}
headers["Authorization"] = fmt.Sprintf("Bearer %v", *sess.Token)
}
req, err := http.NewRequest(opts.Method, opts.URL, opts.Body)
if err != nil {
return nil, err
}
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := FetchHttpClient.Do(req)
if err != nil {
return nil, err
}
if slices.Contains([]int{408, 502, 503, 504}, resp.StatusCode) {
return nil, ErrServerMaintenance
}
retryAfterStr := resp.Header.Get("Retry-After")
if retryAfterStr != "" {
// NOTE: We use milliseconds here even though the API *currently* returns seconds
// to make it easier to change in the future
retryAfter, err := strconv.ParseFloat(retryAfterStr, 64)
if err != nil {
retryAfter = 3000
} else {
retryAfter *= 1000
}
if efo.OnRatelimit != nil {
efo.OnRatelimit(opts, retryAfter, err, sfo, efo.Session)
}
// Wait for the time specified by the server
if !efo.NoWait {
time.Sleep(time.Duration(retryAfter) * time.Second)
if _, err := opts.Body.Seek(0, io.SeekStart); err != nil {
return nil, err
}
if efo.OnRatelimit != nil {
efo.OnRatelimit(opts, 0, err, sfo, efo.Session)
}
continue
}
}
return NewClientResponse(resp), nil
}
}
1 | func Fetch( |
2 | sfo *state.StateFetchOptions, |
3 | efo ExtraFetchOptions, |
4 | opts FetchOptions, |
5 | ) (*ClientResponse, error) { |
6 | for { |
7 | var headers = map[string]string{} |
8 | |
9 | if !efo.NoExtraHeaders { |
10 | headers["Content-Type"] = "application/json" |
11 | } |
12 | |
13 | if len(efo.Headers) > 0 { |
14 | for k, v := range efo.Headers { |
15 | headers[k] = v |
16 | } |
17 | } |
18 | |
19 | if efo.Session != nil { |
20 | sess, err := efo.Session.GetCurrentSession() |
21 | |
22 | if err != nil { |
23 | return nil, err |
24 | } |
25 | |
26 | headers["Authorization"] = fmt.Sprintf("Bearer %v", *sess.Token) |
27 | } |
28 | |
29 | req, err := http.NewRequest(opts.Method, opts.URL, opts.Body) |
30 | |
31 | if err != nil { |
32 | return nil, err |
33 | } |
34 | |
35 | for k, v := range headers { |
36 | req.Header.Set(k, v) |
37 | } |
38 | |
39 | resp, err := FetchHttpClient.Do(req) |
40 | |
41 | if err != nil { |
42 | return nil, err |
43 | } |
44 | |
45 | if slices.Contains([]int{408, 502, 503, 504}, resp.StatusCode) { |
46 | return nil, ErrServerMaintenance |
47 | } |
48 | |
49 | retryAfterStr := resp.Header.Get("Retry-After") |
50 | |
51 | if retryAfterStr != "" { |
52 | // NOTE: We use milliseconds here even though the API *currently* returns seconds |
53 | // to make it easier to change in the future |
54 | retryAfter, err := strconv.ParseFloat(retryAfterStr, 64) |
55 | |
56 | if err != nil { |
57 | retryAfter = 3000 |
58 | } else { |
59 | retryAfter *= 1000 |
60 | } |
61 | |
62 | if efo.OnRatelimit != nil { |
63 | efo.OnRatelimit(opts, retryAfter, err, sfo, efo.Session) |
64 | } |
65 | |
66 | // Wait for the time specified by the server |
67 | if !efo.NoWait { |
68 | time.Sleep(time.Duration(retryAfter) * time.Second) |
69 | |
70 | if _, err := opts.Body.Seek(0, io.SeekStart); err != nil { |
71 | return nil, err |
72 | } |
73 | |
74 | if efo.OnRatelimit != nil { |
75 | efo.OnRatelimit(opts, 0, err, sfo, efo.Session) |
76 | } |
77 | |
78 | continue |
79 | } |
80 | } |
81 | |
82 | return NewClientResponse(resp), nil |
83 | } |
84 | } |
85 |