how to close/abort a Golang http.Client POST prematurely

George Armhold picture George Armhold · Mar 22, 2015 · Viewed 14.9k times · Source

I'm using http.Client for the client-side implementation of a long-poll:

resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonPostBytes))
if err != nil {
    panic(err)
}
defer resp.Body.Close()

var results []*ResponseMessage
err = json.NewDecoder(resp.Body).Decode(&results)  // code blocks here on long-poll

Is there a standard way to pre-empt/cancel the request from the client-side?

I imagine that calling resp.Body.Close() would do it, but I'd have to call that from another goroutine, as the client is normally already blocked in reading the response of the long-poll.

I know that there is a way to set a timeout via http.Transport, but my app logic need to do the cancellation based on a user action, not just a timeout.

Answer

Paulo Casaretto picture Paulo Casaretto · Nov 8, 2016

Using CancelRequest is now deprecated.

The current strategy is to use http.Request.WithContext passing a context with a deadline or that will be canceled otherwise. Just use it like a normal request afterwards.

req, err := http.NewRequest("GET", "http://example.com", nil)
// ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
req = req.WithContext(ctx)
resp, err := client.Do(req)
// ...