-
Notifications
You must be signed in to change notification settings - Fork 1
/
env.go
74 lines (67 loc) · 2.26 KB
/
env.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
package requests
import (
"context"
"net"
"net/http"
"time"
)
type environment struct {
timeout time.Duration
// transport establishes network connections as needed and
// caches them for reuse by subsequent calls. It uses HTTP proxies as
// directed by the environment variables HTTP_PROXY, HTTPS_PROXY and
// NO_PROXY (or the lowercase versions thereof).
transport *http.Transport
interceptor Interceptor
}
var env environment
func init() {
env.timeout = 60 * time.Second // default timeout
// DefaultTransport
// refer: https://github.com/golang/go/blob/c333d07ebe9268efc3cf4bd68319d65818c75966/src/net/http/transport.go#L42
env.transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
// SetEnvTimeout sets the default timeout for each HTTP request at
// the environment level.
func SetEnvTimeout(timeout time.Duration) {
env.timeout = timeout
}
// WithInterceptor specifies the interceptor for each HTTP request.
func WithInterceptor(interceptors ...Interceptor) {
// Prepend env.interceptor to the chaining interceptors if it exists, since
// env.interceptor will be executed before any other chained interceptors.
if env.interceptor != nil {
interceptors = append([]Interceptor{env.interceptor}, interceptors...)
}
var chainedInt Interceptor
if len(interceptors) == 0 {
chainedInt = nil
} else if len(interceptors) == 1 {
chainedInt = interceptors[0]
} else {
chainedInt = func(ctx context.Context, r *Request, do Do) (*Response, error) {
return interceptors[0](ctx, r, getChainDo(interceptors, 0, do))
}
}
env.interceptor = chainedInt
}
// getChainDo recursively generates the chained do.
func getChainDo(interceptors []Interceptor, curr int, finalDo Do) Do {
if curr == len(interceptors)-1 {
return finalDo
}
return func(ctx context.Context, r *Request) (*Response, error) {
return interceptors[curr+1](ctx, r, getChainDo(interceptors, curr+1, finalDo))
}
}