Last active
August 3, 2017 05:35
-
-
Save c4milo/275abc6eccbfd88ad56ca7c77947883a to your computer and use it in GitHub Desktop.
HTTP client with support for read and write timeouts which are missing in Go's standard library.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package httpclient | |
import ( | |
"context" | |
"net" | |
"net/http" | |
"time" | |
) | |
// DialContextFn was defined to make code more readable. | |
type dialContextFn func(ctx context.Context, network, address string) (net.Conn, error) | |
// DialContext implements our own dialer in order to set read and write idle timeouts. | |
func DialContext(rwtimeout, ctimeout time.Duration) dialContextFn { | |
dialer := &net.Dialer{Timeout: ctimeout} | |
return func(ctx context.Context, network, addr string) (net.Conn, error) { | |
c, err := dialer.DialContext(ctx, network, addr) | |
if err != nil { | |
return nil, err | |
} | |
if rwtimeout > 0 { | |
timeoutConn := &tcpConn{ | |
TCPConn: c.(*net.TCPConn), | |
timeout: rwtimeout, | |
} | |
return timeoutConn, nil | |
} | |
return c, nil | |
} | |
} | |
// tcpConn is our own net.Conn which sets a read and write deadline and resets them each | |
// time there is read or write activity in the connection. | |
type tcpConn struct { | |
*net.TCPConn | |
timeout time.Duration | |
} | |
func (c *tcpConn) Read(b []byte) (int, error) { | |
err := c.TCPConn.SetDeadline(time.Now().Add(c.timeout)) | |
if err != nil { | |
return 0, err | |
} | |
return c.TCPConn.Read(b) | |
} | |
func (c *tcpConn) Write(b []byte) (int, error) { | |
err := c.TCPConn.SetDeadline(time.Now().Add(c.timeout)) | |
if err != nil { | |
return 0, err | |
} | |
return c.TCPConn.Write(b) | |
} | |
// DefaultClient returns a default client with sensible values for slow 3G connections and above. | |
func DefaultClient() *http.Client { | |
return &http.Client{ | |
Transport: &http.Transport{ | |
DialContext: DialContext(30*time.Second, 10*time.Second), | |
Proxy: http.ProxyFromEnvironment, | |
MaxIdleConns: 100, | |
IdleConnTimeout: 30 * time.Second, | |
TLSHandshakeTimeout: 10 * time.Second, | |
ExpectContinueTimeout: 1 * time.Second, | |
ResponseHeaderTimeout: 10 * time.Second, | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment