oss/transport/http.go (143 lines of code) (raw):

package transport import ( "crypto/tls" "net/http" "net/url" "time" ) // Defaults for the Transport var ( DefaultConnectTimeout = 5 * time.Second DefaultReadWriteTimeout = 10 * time.Second DefaultIdleConnectionTimeout = 50 * time.Second DefaultExpectContinueTimeout = 1 * time.Second DefaultKeepAliveTimeout = 30 * time.Second DefaultMaxConnections = 100 // Default to TLS 1.2 for all HTTPS requests. DefaultTLSMinVersion uint16 = tls.VersionTLS12 ) var DefaultConfig = Config{ ConnectTimeout: &DefaultConnectTimeout, ReadWriteTimeout: &DefaultReadWriteTimeout, IdleConnectionTimeout: &DefaultIdleConnectionTimeout, KeepAliveTimeout: &DefaultKeepAliveTimeout, } type Config struct { ConnectTimeout *time.Duration ReadWriteTimeout *time.Duration IdleConnectionTimeout *time.Duration KeepAliveTimeout *time.Duration EnabledRedirect *bool PostRead []func(n int, err error) PostWrite []func(n int, err error) } func newTransportCustom(cfg *Config, fns ...func(*http.Transport)) http.RoundTripper { tr := &http.Transport{ DialContext: newDialer(cfg).DialContext, TLSHandshakeTimeout: *cfg.ConnectTimeout, IdleConnTimeout: *cfg.IdleConnectionTimeout, MaxConnsPerHost: DefaultMaxConnections, ExpectContinueTimeout: DefaultExpectContinueTimeout, TLSClientConfig: &tls.Config{ MinVersion: DefaultTLSMinVersion, }, } for _, fn := range fns { fn(tr) } return tr } func (c *Config) mergeIn(cfgs ...*Config) { for _, other := range cfgs { mergeInConfig(c, other) } } func (c *Config) copy(cfgs ...*Config) *Config { dst := &Config{} dst.mergeIn(c) for _, cfg := range cfgs { dst.mergeIn(cfg) } return dst } func mergeInConfig(dst *Config, other *Config) { if other == nil { return } if other.ConnectTimeout != nil { dst.ConnectTimeout = other.ConnectTimeout } if other.ReadWriteTimeout != nil { dst.ReadWriteTimeout = other.ReadWriteTimeout } if other.IdleConnectionTimeout != nil { dst.IdleConnectionTimeout = other.IdleConnectionTimeout } if other.KeepAliveTimeout != nil { dst.KeepAliveTimeout = other.KeepAliveTimeout } if other.EnabledRedirect != nil { dst.EnabledRedirect = other.EnabledRedirect } if other.PostRead != nil { dst.PostRead = make([]func(n int, err error), len(other.PostRead)) copy(dst.PostRead, other.PostRead) } if other.PostWrite != nil { dst.PostWrite = make([]func(n int, err error), len(other.PostWrite)) copy(dst.PostWrite, other.PostWrite) } } func InsecureSkipVerify(enabled bool) func(*http.Transport) { return func(t *http.Transport) { if t.TLSClientConfig != nil { t.TLSClientConfig.InsecureSkipVerify = enabled } else { t.TLSClientConfig = &tls.Config{ InsecureSkipVerify: enabled, } } } } func MaxConnections(value int) func(*http.Transport) { return func(t *http.Transport) { t.MaxConnsPerHost = value } } func ExpectContinueTimeout(value time.Duration) func(*http.Transport) { return func(t *http.Transport) { t.ExpectContinueTimeout = value } } func TLSMinVersion(value int) func(*http.Transport) { return func(t *http.Transport) { if t.TLSClientConfig != nil { t.TLSClientConfig.MinVersion = uint16(value) } else { t.TLSClientConfig = &tls.Config{ MinVersion: uint16(value), } } } } func HttpProxy(fixedURL *url.URL) func(*http.Transport) { return func(t *http.Transport) { t.Proxy = http.ProxyURL(fixedURL) } } func ProxyFromEnvironment() func(*http.Transport) { return func(t *http.Transport) { t.Proxy = http.ProxyFromEnvironment } } func NewHttpClient(cfg *Config, fns ...func(*http.Transport)) *http.Client { cfg = DefaultConfig.copy(cfg) client := &http.Client{ Transport: newTransportCustom(cfg, fns...), //Disalbe Redirect CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, } if cfg.EnabledRedirect != nil && *cfg.EnabledRedirect { client.CheckRedirect = nil } return client }