|
6 | 6 | "errors"
|
7 | 7 | "fmt"
|
8 | 8 | "io"
|
| 9 | + "net" |
| 10 | + "net/http" |
9 | 11 | "net/url"
|
10 | 12 | "os"
|
11 | 13 | "runtime/debug"
|
@@ -114,6 +116,35 @@ type Options struct {
|
114 | 116 | // is currently 20s.
|
115 | 117 | InitTimeout time.Duration `yaml:"init_timeout"`
|
116 | 118 |
|
| 119 | + // IdleConnTimeout is the maximum amount of time an idle |
| 120 | + // (keep-alive) connection will remain idle before closing |
| 121 | + // itself. Default if unset: 90s |
| 122 | + IdleConnTimeout time.Duration `yaml:"idle_conn_timeout"` |
| 123 | + |
| 124 | + // MaxIdleConns controls the maximum number of idle (keep-alive) |
| 125 | + // connections. Default if unset: 100 |
| 126 | + MaxIdleConns int `yaml:"max_idle_conns"` |
| 127 | + |
| 128 | + // DialTimeout is the maximum amount of time a dial will wait for |
| 129 | + // a connect to complete. Default if unset: 10s |
| 130 | + DialTimeout time.Duration `yaml:"dial_timeout"` |
| 131 | + |
| 132 | + // DialKeepAlive specifies the interval between keep-alive |
| 133 | + // probes for an active network connection. Default if unset: 10s |
| 134 | + DialKeepAlive time.Duration `yaml:"dial_keep_alive"` |
| 135 | + |
| 136 | + // TLSHandshakeTimeout specifies the maximum amount of time to |
| 137 | + // wait for a TLS handshake. Default if unset: 10s |
| 138 | + TLSHandshakeTimeout time.Duration `yaml:"tls_handshake_timeout"` |
| 139 | + |
| 140 | + // ClientTimeout specifies a time limit for requests made by this |
| 141 | + // HTTP Client. The timeout includes connection time, any |
| 142 | + // redirects, and reading the response body. The timer remains |
| 143 | + // running after Get, Head, Post, or Do return and will |
| 144 | + // interrupt reading of the Response.Body. |
| 145 | + // Default if unset: 15m |
| 146 | + ClientTimeout time.Duration `yaml:"client_timeout"` |
| 147 | + |
117 | 148 | // UseUpdateMarker makes the backend write and read a file to determine if
|
118 | 149 | // it can cache the last List command. The file contains the name of the
|
119 | 150 | // last file stored or deleted.
|
@@ -394,15 +425,34 @@ func New(ctx context.Context, opt Options) (*Backend, error) {
|
394 | 425 | if err != nil {
|
395 | 426 | return nil, err
|
396 | 427 | }
|
397 |
| - // Get an opinionated HTTP client that: |
| 428 | + |
| 429 | + // Create an opinionated HTTP client that: |
398 | 430 | // - Uses a custom tls.Config
|
399 | 431 | // - Sets proxies from the environment
|
400 | 432 | // - Sets reasonable timeouts on various operations
|
401 |
| - // Check the implementation for details. |
402 |
| - hc, err := tlsmgr.HTTPClient() |
| 433 | + // Based on tlsConfig.HTTPClient(), copied to allow overrides. |
| 434 | + tlsConfig, err := tlsmgr.TLSConfig() |
403 | 435 | if err != nil {
|
404 | 436 | return nil, err
|
405 | 437 | }
|
| 438 | + transport := &http.Transport{ |
| 439 | + Proxy: http.ProxyFromEnvironment, |
| 440 | + DialContext: (&net.Dialer{ |
| 441 | + Timeout: getOpt(opt.DialTimeout, 10*time.Second), |
| 442 | + KeepAlive: getOpt(opt.DialKeepAlive, 10*time.Second), |
| 443 | + }).DialContext, |
| 444 | + MaxIdleConns: getOpt(opt.MaxIdleConns, 100), |
| 445 | + IdleConnTimeout: getOpt(opt.IdleConnTimeout, 90*time.Second), |
| 446 | + TLSHandshakeTimeout: getOpt(opt.TLSHandshakeTimeout, 10*time.Second), |
| 447 | + ExpectContinueTimeout: 10 * time.Second, |
| 448 | + TLSClientConfig: tlsConfig, |
| 449 | + ForceAttemptHTTP2: true, |
| 450 | + } |
| 451 | + hc := &http.Client{ |
| 452 | + Transport: transport, |
| 453 | + // includes reading response body! |
| 454 | + Timeout: getOpt(opt.ClientTimeout, 15*time.Minute), |
| 455 | + } |
406 | 456 |
|
407 | 457 | // Some of the following calls require a short running context
|
408 | 458 | ctx, cancel := context.WithTimeout(ctx, opt.InitTimeout)
|
@@ -505,6 +555,14 @@ func convertMinioError(err error, isList bool) error {
|
505 | 555 | return err
|
506 | 556 | }
|
507 | 557 |
|
| 558 | +func getOpt[T comparable](optVal, defaultVal T) T { |
| 559 | + var zero T |
| 560 | + if optVal == zero { |
| 561 | + return defaultVal |
| 562 | + } |
| 563 | + return optVal |
| 564 | +} |
| 565 | + |
508 | 566 | // prependGlobalPrefix prepends the GlobalPrefix to the name/prefix
|
509 | 567 | // passed as input
|
510 | 568 | func (b *Backend) prependGlobalPrefix(name string) string {
|
|
0 commit comments