/
client.go
102 lines (89 loc) · 2.37 KB
/
client.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
package gorest
import (
"net/http"
"net/url"
"strconv"
"strings"
"time"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/flowcontrol"
)
var (
// longThrottleLatency defines threshold for logging requests. All requests being
// throttled (via the provided rateLimiter) for more than longThrottleLatency will
// be logged.
longThrottleLatency = 50 * time.Millisecond
// extraLongThrottleLatency defines the threshold for logging requests at log level 2.
extraLongThrottleLatency = 1 * time.Second
)
var noBackoff = &rest.NoBackoff{}
type RESTClient struct {
Client *http.Client
createBackoffMgr func() rest.BackoffManager
rateLimiter flowcontrol.RateLimiter
}
func NewDefaultRESTClient() *RESTClient {
return &RESTClient{
createBackoffMgr: readExpBackoffConfig,
rateLimiter: flowcontrol.NewTokenBucketRateLimiter(100.00, 10),
Client: &http.Client{},
}
}
func FastNewRESTClientWithProxy(baseURL, proxyUrl string) *RESTClient {
var (
base *url.URL
client *http.Client
)
parsedUrl, err := url.Parse(baseURL)
if err != nil {
base = new(url.URL)
} else {
base = parsedUrl
}
if !strings.HasSuffix(base.Path, "/") {
base.Path += "/"
}
base.RawQuery = ""
base.Fragment = ""
parsedProxyUrl, err := url.Parse(proxyUrl)
if err != nil {
client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
},
}
} else {
client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(parsedProxyUrl),
},
}
}
return &RESTClient{
createBackoffMgr: readExpBackoffConfig,
rateLimiter: flowcontrol.NewTokenBucketRateLimiter(100.00, 10),
Client: client,
}
}
// checkWait returns true along with a number of seconds if the server instructed us to wait
// before retrying.
func checkWait(resp *http.Response) (int, bool) {
switch r := resp.StatusCode; {
// any 500 error code and 429 can trigger a wait
case r == http.StatusTooManyRequests, r >= 500:
default:
return 0, false
}
i, ok := retryAfterSeconds(resp)
return i, ok
}
// retryAfterSeconds returns the value of the Retry-After header and true, or 0 and false if
// the header was missing or not a valid number.
func retryAfterSeconds(resp *http.Response) (int, bool) {
if h := resp.Header.Get("Retry-After"); len(h) > 0 {
if i, err := strconv.Atoi(h); err == nil {
return i, true
}
}
return 0, false
}