Skip to content

Commit

Permalink
Teach http client to cancel request on context cancellation
Browse files Browse the repository at this point in the history
The context may be cancelled while a request is in flight. We need to
handle this and cancel the request. The code is based on the ideas
from https://blog.golang.org/context
  • Loading branch information
torarnv authored and Tor Arne Vestbø committed Apr 20, 2015
1 parent 3d05764 commit 661fb0a
Showing 1 changed file with 36 additions and 17 deletions.
53 changes: 36 additions & 17 deletions commands/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,44 @@ func (c *client) Send(req cmds.Request) (cmds.Response, error) {
version := config.CurrentVersionNumber
httpReq.Header.Set("User-Agent", fmt.Sprintf("/go-ipfs/%s/", version))

httpRes, err := http.DefaultClient.Do(httpReq)
if err != nil {
return nil, err
}

// using the overridden JSON encoding in request
res, err := getResponse(httpRes, req)
if err != nil {
return nil, err
}
ec := make(chan error, 1)
rc := make(chan cmds.Response, 1)
dc := req.Context().Context.Done()

if found && len(previousUserProvidedEncoding) > 0 {
// reset to user provided encoding after sending request
// NB: if user has provided an encoding but it is the empty string,
// still leave it as JSON.
req.SetOption(cmds.EncShort, previousUserProvidedEncoding)
go func() {
httpRes, err := http.DefaultClient.Do(httpReq)
if err != nil {
ec <- err
return
}
// using the overridden JSON encoding in request
res, err := getResponse(httpRes, req)
if err != nil {
ec <- err
return
}
rc <- res
}()

for {
select {
case <-dc:
log.Debug("Context cancelled, cancelling HTTP request...")
tr := http.DefaultTransport.(*http.Transport)
tr.CancelRequest(httpReq)
dc = nil // Wait for ec or rc
case err := <-ec:
return nil, err
case res := <-rc:
if found && len(previousUserProvidedEncoding) > 0 {
// reset to user provided encoding after sending request
// NB: if user has provided an encoding but it is the empty string,
// still leave it as JSON.
req.SetOption(cmds.EncShort, previousUserProvidedEncoding)
}
return res, nil
}
}

return res, nil
}

func getQuery(req cmds.Request) (string, error) {
Expand Down

0 comments on commit 661fb0a

Please sign in to comment.