Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify timeout when tracing HTTP request in Go

Tags:

http

go

I know the usual method of specifying a timeout with HTTP requests by doing:

httpClient := http.Client{
    Timeout: time.Duration(5 * time.Second),
}

However, I can't seem to figure out how to do the same when tracing HTTP requests. Here is the piece of code I am working with:

func timeGet(url string) (httpTimingBreakDown, error) {
    req, _ := http.NewRequest("GET", url, nil)

    var start, connect, dns, tlsHandshake time.Time
    var timingData httpTimingBreakDown
    timingData.url = url

    trace := &httptrace.ClientTrace{
        TLSHandshakeStart:    func() { tlsHandshake = time.Now() },
        TLSHandshakeDone:     func(cs tls.ConnectionState, err error) { timingData.tls = time.Since(tlsHandshake) },
    }

    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
    start = time.Now()

    http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 10 // hacky way, worked earlier but don't work anymore

    if _, err := http.DefaultTransport.RoundTrip(req); err != nil {
        fmt.Println(err)
        return timingData, err
    }

    timingData.total = time.Since(start)

    return timingData, nil
}

I am firing this function inside a goroutine. My sample data set is 100 urls. All goroutines fire, but eventually the program ends in 30+ secs as if the timeout is 30secs.

Earlier I made the same to work by using the hacky way of changing the default inside of it to 10 secs and anything that took too long, timed out and the program ended at 10.xxx secs but now its taking 30.xx secs.

What would be a proper way of specifying a timeout in this scenario?

like image 230
Ashfame Avatar asked Feb 21 '18 08:02

Ashfame


People also ask

How would you set a timeout on an HTTP request?

Timeouts on http. request() takes a timeout option. Its documentation says: timeout <number> : A number specifying the socket timeout in milliseconds. This will set the timeout before the socket is connected.

What is the default timeout for HTTP request?

The default value is 100,000 milliseconds (100 seconds).

How do you handle HTTP requests in go?

Making a GET Request. The Go net/http package has a few different ways to use it as a client. You can use a common, global HTTP client with functions such as http. Get to quickly make an HTTP GET request with only a URL and a body, or you can create an http.

Does HTTP have a timeout?

A Request-Timeout header is defined for Hypertext Transfer Protocol (HTTP). This end-to-end header informs an origin server and any intermediaries of the maximum time that a client will await a response to its request. A server can use this header to ensure that a timely response is generated.


1 Answers

I know the usual method of specifying a timeout with HTTP requests by doing:

httpClient := http.Client{
    Timeout: time.Duration(5 * time.Second),
}

Actually, the preferred method is to use a context.Context on the request. The method you've used is just a short-cut suitable for simple use cases.

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
    return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()
req = req.WithContext(ctx)

And this method should work nicely for your situation as well.

like image 143
Flimzy Avatar answered Oct 12 '22 12:10

Flimzy