@@ -17,11 +17,13 @@ package config
17
17
18
18
import (
19
19
"bytes"
20
+ "context"
20
21
"crypto/sha256"
21
22
"crypto/tls"
22
23
"crypto/x509"
23
24
"fmt"
24
25
"io/ioutil"
26
+ "net"
25
27
"net/http"
26
28
"net/url"
27
29
"strings"
@@ -194,15 +196,33 @@ func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error {
194
196
return unmarshal ((* plain )(a ))
195
197
}
196
198
199
+ // DialContextFunc defines the signature of the DialContext() function implemented
200
+ // by net.Dialer.
201
+ type DialContextFunc func (context.Context , string , string ) (net.Conn , error )
202
+
203
+ type httpClientOptions struct {
204
+ dialContextFunc DialContextFunc
205
+ }
206
+
207
+ // HTTPClientOption defines an option that can be applied to the HTTP client.
208
+ type HTTPClientOption func (options * httpClientOptions )
209
+
210
+ // WithDialContextFunc allows you to override func gets used for the actual dialing. The default is `net.Dialer.DialContext`.
211
+ func WithDialContextFunc (fn DialContextFunc ) HTTPClientOption {
212
+ return func (opts * httpClientOptions ) {
213
+ opts .dialContextFunc = fn
214
+ }
215
+ }
216
+
197
217
// NewClient returns a http.Client using the specified http.RoundTripper.
198
218
func newClient (rt http.RoundTripper ) * http.Client {
199
219
return & http.Client {Transport : rt }
200
220
}
201
221
202
222
// NewClientFromConfig returns a new HTTP client configured for the
203
223
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
204
- func NewClientFromConfig (cfg HTTPClientConfig , name string , disableKeepAlives , enableHTTP2 bool ) (* http.Client , error ) {
205
- rt , err := NewRoundTripperFromConfig (cfg , name , disableKeepAlives , enableHTTP2 )
224
+ func NewClientFromConfig (cfg HTTPClientConfig , name string , disableKeepAlives , enableHTTP2 bool , optFuncs ... HTTPClientOption ) (* http.Client , error ) {
225
+ rt , err := NewRoundTripperFromConfig (cfg , name , disableKeepAlives , enableHTTP2 , optFuncs ... )
206
226
if err != nil {
207
227
return nil , err
208
228
}
@@ -217,7 +237,25 @@ func NewClientFromConfig(cfg HTTPClientConfig, name string, disableKeepAlives, e
217
237
218
238
// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
219
239
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
220
- func NewRoundTripperFromConfig (cfg HTTPClientConfig , name string , disableKeepAlives , enableHTTP2 bool ) (http.RoundTripper , error ) {
240
+ func NewRoundTripperFromConfig (cfg HTTPClientConfig , name string , disableKeepAlives , enableHTTP2 bool , optFuncs ... HTTPClientOption ) (http.RoundTripper , error ) {
241
+ opts := & httpClientOptions {}
242
+ for _ , f := range optFuncs {
243
+ f (opts )
244
+ }
245
+
246
+ var dialContext func (ctx context.Context , network , addr string ) (net.Conn , error )
247
+
248
+ if opts .dialContextFunc != nil {
249
+ dialContext = conntrack .NewDialContextFunc (
250
+ conntrack .DialWithDialContextFunc ((func (context.Context , string , string ) (net.Conn , error ))(opts .dialContextFunc )),
251
+ conntrack .DialWithTracing (),
252
+ conntrack .DialWithName (name ))
253
+ } else {
254
+ dialContext = conntrack .NewDialContextFunc (
255
+ conntrack .DialWithTracing (),
256
+ conntrack .DialWithName (name ))
257
+ }
258
+
221
259
newRT := func (tlsConfig * tls.Config ) (http.RoundTripper , error ) {
222
260
// The only timeout we care about is the configured scrape timeout.
223
261
// It is applied on request. So we leave out any timings here.
@@ -233,10 +271,7 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, disableKeepAli
233
271
IdleConnTimeout : 5 * time .Minute ,
234
272
TLSHandshakeTimeout : 10 * time .Second ,
235
273
ExpectContinueTimeout : 1 * time .Second ,
236
- DialContext : conntrack .NewDialContextFunc (
237
- conntrack .DialWithTracing (),
238
- conntrack .DialWithName (name ),
239
- ),
274
+ DialContext : dialContext ,
240
275
}
241
276
if enableHTTP2 {
242
277
// HTTP/2 support is golang has many problematic cornercases where
0 commit comments