amuz.es/src/infra/goutils@v0.1.3/http/client/client.go (about) 1 package client 2 3 import ( 4 "net/http" 5 "net" 6 "time" 7 "errors" 8 "net/url" 9 "io" 10 ) 11 12 var ( 13 httpCannotRedirectError = errors.New("this client cannot redirect") 14 15 disableRedirect = func(_ *http.Request, _ []*http.Request) error { 16 return httpCannotRedirectError 17 } 18 limitedRedirect = func(_ *http.Request, via []*http.Request) error { 19 if len(via) >= 10 { 20 return errors.New("stopped after 10 redirects") 21 } 22 return nil 23 } 24 ) 25 26 type GracefulClient interface { 27 http.RoundTripper 28 client() *http.Client 29 roundTripper() http.RoundTripper 30 Do(req *http.Request) (*http.Response, error) 31 Get(url string) (resp *http.Response, err error) 32 Head(url string) (resp *http.Response, err error) 33 Post(url string, contentType string, body io.Reader) (resp *http.Response, err error) 34 PostForm(url string, data url.Values) (resp *http.Response, err error) 35 } 36 37 38 type wrappedClient struct { 39 http.Client 40 } 41 42 func (cli *wrappedClient) client() (*http.Client) { 43 return &cli.Client 44 } 45 func (cli *wrappedClient) roundTripper() http.RoundTripper { 46 return cli.Transport 47 } 48 49 func (cli *wrappedClient) RoundTrip(req *http.Request) (*http.Response, error) { 50 return cli.Client.Transport.RoundTrip(req) 51 } 52 53 func NewClient( 54 keepaliveDuration time.Duration, 55 connectTimeout time.Duration, 56 responseHeaderTimeout time.Duration, 57 idleConnectionTimeout time.Duration, 58 maxIdleConnections int, 59 redirectSupport bool, 60 serverName string, 61 ) GracefulClient { 62 63 srvName := []string{serverName} 64 var redirectChecker func(*http.Request, []*http.Request) error 65 if redirectSupport { 66 redirectChecker = limitedRedirect 67 } else { 68 redirectChecker = disableRedirect 69 } 70 71 keepaliveDisabled := keepaliveDuration == 0 72 dialer := &net.Dialer{ 73 Timeout: connectTimeout, 74 KeepAlive: keepaliveDuration, 75 DualStack: false, 76 } 77 78 transport := &predefinedHeaderTransport{ 79 useragentName: srvName, 80 Transport: http.Transport{ 81 Proxy: nil, 82 DialTLS: nil, 83 TLSClientConfig: nil, 84 DisableKeepAlives: keepaliveDisabled, 85 DisableCompression: true, 86 MaxIdleConnsPerHost: maxIdleConnections, 87 DialContext: dialer.DialContext, 88 MaxIdleConns: maxIdleConnections, 89 IdleConnTimeout: idleConnectionTimeout, 90 ResponseHeaderTimeout: responseHeaderTimeout, 91 TLSNextProto: nil, 92 ExpectContinueTimeout: 0, 93 }, 94 } 95 96 return &wrappedClient{ 97 Client: http.Client{ 98 Transport: transport, 99 CheckRedirect: redirectChecker, 100 Jar: nil, 101 }, 102 } 103 }