-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
client.go
141 lines (122 loc) · 4.9 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
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
package handcash
import (
"net"
"net/http"
"time"
"github.com/gojektech/heimdall/v6"
"github.com/gojektech/heimdall/v6/httpclient"
)
// httpInterface is used for the http client (mocking heimdall)
type httpInterface interface {
Do(req *http.Request) (*http.Response, error)
}
// Client is the parent struct that contains the miner clients and list of miners to use
type Client struct {
Environment *Environment // Current environment for the client
httpClient httpInterface // Interface for all HTTP requests
Options *ClientOptions // Client options config
}
// ClientOptions holds all the configuration for connection, dialer and transport
type ClientOptions struct {
BackOffExponentFactor float64 `json:"back_off_exponent_factor"`
BackOffInitialTimeout time.Duration `json:"back_off_initial_timeout"`
BackOffMaximumJitterInterval time.Duration `json:"back_off_maximum_jitter_interval"`
BackOffMaxTimeout time.Duration `json:"back_off_max_timeout"`
DialerKeepAlive time.Duration `json:"dialer_keep_alive"`
DialerTimeout time.Duration `json:"dialer_timeout"`
RequestRetryCount int `json:"request_retry_count"`
RequestTimeout time.Duration `json:"request_timeout"`
TransportExpectContinueTimeout time.Duration `json:"transport_expect_continue_timeout"`
TransportIdleTimeout time.Duration `json:"transport_idle_timeout"`
TransportMaxIdleConnections int `json:"transport_max_idle_connections"`
TransportTLSHandshakeTimeout time.Duration `json:"transport_tls_handshake_timeout"`
UserAgent string `json:"user_agent"`
}
// DefaultClientOptions will return an Options struct with the default settings.
// Useful for starting with the default and then modifying as needed
func DefaultClientOptions() (clientOptions *ClientOptions) {
return &ClientOptions{
BackOffExponentFactor: 2.0,
BackOffInitialTimeout: 2 * time.Millisecond,
BackOffMaximumJitterInterval: 2 * time.Millisecond,
BackOffMaxTimeout: 10 * time.Millisecond,
DialerKeepAlive: 20 * time.Second,
DialerTimeout: 5 * time.Second,
RequestRetryCount: 2,
RequestTimeout: 10 * time.Second,
TransportExpectContinueTimeout: 3 * time.Second,
TransportIdleTimeout: 20 * time.Second,
TransportMaxIdleConnections: 10,
TransportTLSHandshakeTimeout: 5 * time.Second,
UserAgent: defaultUserAgent,
}
}
// Environment is the Handcash environment information
type Environment struct {
APIURL string `json:"api_url"`
ClientURL string `json:"client_url"`
Environment string `json:"environment"`
}
// NewClient creates a new client for requests
// If no environment is set, production is used as the default
func NewClient(options *ClientOptions, customHTTPClient *http.Client,
customEnvironment string) (c *Client) {
// Create a client
c = new(Client)
// Set options (either default or user modified)
if options == nil {
options = DefaultClientOptions()
}
// Set the options
c.Options = options
// Set the environment
var found bool
if c.Environment, found = environments[customEnvironment]; !found {
c.Environment = environments[EnvironmentProduction]
}
// Is there a custom HTTP client to use?
if customHTTPClient != nil {
c.httpClient = customHTTPClient
return
}
// dial is the net dialer for clientDefaultTransport
dial := &net.Dialer{KeepAlive: options.DialerKeepAlive, Timeout: options.DialerTimeout}
// clientDefaultTransport is the default transport struct for the HTTP client
clientDefaultTransport := &http.Transport{
DialContext: dial.DialContext,
ExpectContinueTimeout: options.TransportExpectContinueTimeout,
IdleConnTimeout: options.TransportIdleTimeout,
MaxIdleConns: options.TransportMaxIdleConnections,
Proxy: http.ProxyFromEnvironment,
TLSHandshakeTimeout: options.TransportTLSHandshakeTimeout,
}
// Determine the strategy for the http client
if options.RequestRetryCount <= 0 {
// no retry enabled
c.httpClient = httpclient.NewClient(
httpclient.WithHTTPTimeout(options.RequestTimeout),
httpclient.WithHTTPClient(&http.Client{
Transport: clientDefaultTransport,
Timeout: options.RequestTimeout,
}),
)
return
}
// Retry enabled - create exponential back-off
c.httpClient = httpclient.NewClient(
httpclient.WithHTTPTimeout(options.RequestTimeout),
httpclient.WithRetrier(heimdall.NewRetrier(
heimdall.NewExponentialBackoff(
options.BackOffInitialTimeout,
options.BackOffMaxTimeout,
options.BackOffExponentFactor,
options.BackOffMaximumJitterInterval,
))),
httpclient.WithRetryCount(options.RequestRetryCount),
httpclient.WithHTTPClient(&http.Client{
Transport: clientDefaultTransport,
Timeout: options.RequestTimeout,
}),
)
return
}