Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go http client timeout vs context timeout

Tags:

http

go

go-http

What's the difference between timeout set in http.Client and timeout set in request's context?

I've seen 2 ways of setting timeout in http client.

First:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:8080", nil)

Second:

client := http.Client{
    Timeout: 2 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
    panic(err)
}

when to use one over the other?

like image 556
Jake Muller Avatar asked Sep 30 '20 00:09

Jake Muller


People also ask

What is HttpClient timeout?

If your request contains a host name that requires resolution and you set Timeout to a value less than 15 seconds, it may take 15 seconds or more before a WebException is thrown to indicate a timeout on your request. The same timeout will apply for all requests using this HttpClient instance.

Is Golang HTTP client thread safe?

Http clients are thread safe according to the docs (https://golang.org/src/net/http/client.go): Clients are safe for concurrent use by multiple goroutines.

What is HTTP response timeout?

The HyperText Transfer Protocol (HTTP) 408 Request Timeout response status code means that the server would like to shut down this unused connection. It is sent on an idle connection by some servers, even without any previous request by the client.

How do you add timeout in Golang?

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.


2 Answers

Both can achieve the same thing which is to terminate the request due to timeout.

But using context is the preferred way as it's made for this task. The field timeout exist before context added to Go. You have to pick one for timeout at the time creating the request as the the request will pick the smaller timeout to be applied, rendering other useless. In this case the preferable method is using the context timeout as you have more control over it, you can use cancel without specifying timeout in case you want to cancel the request by logic decision. Using context you can also pass any values through it describing request scope values.

Using context is request specific, while using the Client timeout might be applied to all request pass to Do method client has. If you want to specialise your deadline/timeout to each request then use context, otherwise if you want 1 timeout for every outbound request then using client timeout is enough.

You can also read about it here Specify timeout when tracing HTTP request in Go

like image 170
mfathirirhas Avatar answered Oct 26 '22 01:10

mfathirirhas


Normally we would use this method when we only want to put a timeout for a http request only

client := http.Client{
    Timeout: 2 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
    panic(err)
}

I think the question is when should we be using contexts, if you go to documentation you will find

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

So lets say you have a API that needs to respond in under some time and you need a way to track all go routines it creates and want to signal them all at the same time to stop; this is the use case where it makes sense to use a context and pass it to all the go routines created by one API call and it becomes really easy to know when the context expired and when everyone needs to stop working.

Although The way you do http request will work but it does not make much sense that you create a context that is explicit to a particular request unless lets say your request is run in a goroutine and you need to pass a cancel signal due to some other inputs you received after executing it.

Ideally in most circumstances context is used to scope a chain of requests/ goroutines you need to signal.

You should read this for more clarity of when to use context https://blog.golang.org/context

like image 3
Shubham Srivastava Avatar answered Oct 26 '22 00:10

Shubham Srivastava