Syntax. The After function waits for d duration to finish and then it will return the current time on a channel. Consider the code shown below where we make use of the After function to register a timeout. package main import ( "fmt" "time" ) func timeConsuming() string { time.
on('timeout', function() { req. abort(); }); req. write('something'); req. end();
With Golang, the approach to handling this has become as simple as it gets. Without using any complicated code, we can handle timeouts by using channels for communication and the select statement for timeout decisions. For more details on the above features, you read the Golang documentation here.
Apparently in Go 1.3 http.Client has Timeout field
client := http.Client{
Timeout: 5 * time.Second,
}
client.Get(url)
That's done the trick for me.
You need to set up your own Client with your own Transport which uses a custom Dial function which wraps around DialTimeout.
Something like (completely untested) this:
var timeout = time.Duration(2 * time.Second)
func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
func main() {
transport := http.Transport{
Dial: dialTimeout,
}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://some.url")
}
To add to Volker's answer, if you would also like to set the read/write timeout in addition to the connect timeout you can do something like the following
package httpclient
import (
"net"
"net/http"
"time"
)
func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) {
return func(netw, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(netw, addr, cTimeout)
if err != nil {
return nil, err
}
conn.SetDeadline(time.Now().Add(rwTimeout))
return conn, nil
}
}
func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client {
return &http.Client{
Transport: &http.Transport{
Dial: TimeoutDialer(connectTimeout, readWriteTimeout),
},
}
}
This code is tested and is working in production. The full gist with tests is available here https://gist.github.com/dmichael/5710968
Be aware that you will need to create a new client for each request because of the conn.SetDeadline
which references a point in the future from time.Now()
If you want to do it per request, err handling ignored for brevity:
ctx, cncl := context.WithTimeout(context.Background(), time.Second*3)
defer cncl()
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://google.com", nil)
resp, _ := http.DefaultClient.Do(req)
A quick and dirty way:
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45
This is mutating global state w/o any coordination. Yet it might be possibly okay for your url fetcher. Otherwise create a private instance of http.RoundTripper
:
var myTransport http.RoundTripper = &http.Transport{
Proxy: http.ProxyFromEnvironment,
ResponseHeaderTimeout: time.Second * 45,
}
var myClient = &http.Client{Transport: myTransport}
resp, err := myClient.Get(url)
...
Nothing above was tested.
You may use https://github.com/franela/goreq which handles timeouts in a fashion and simple way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With