@cryptotaxi247 / kubo / commits / 661fb0a4b

Teach http client to cancel request on context cancellation

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

Tor Arne Vestbø committed Apr 17, 2015 at 18:22 UTC 661fb0a4b500d91944a30734d4d1f18bb3146aef
1 file changed +36 -17
commands/http/client.go
+36 -17
@@ -82,25 +82,44 @@ func (c *client) Send(req cmds.Request) (cmds.Response, error) {
82 version := config.CurrentVersionNumber
83 httpReq.Header.Set("User-Agent", fmt.Sprintf("/go-ipfs/%s/", version))
84
85 - httpRes, err := http.DefaultClient.Do(httpReq)
86 - if err != nil {
87 - return nil, err
88 - }
89 -
90 - // using the overridden JSON encoding in request
91 - res, err := getResponse(httpRes, req)
92 - if err != nil {
93 - return nil, err
94 - }
85 + ec := make(chan error, 1)
86 + rc := make(chan cmds.Response, 1)
87 + dc := req.Context().Context.Done()
88
96 - if found && len(previousUserProvidedEncoding) > 0 {
97 - // reset to user provided encoding after sending request
98 - // NB: if user has provided an encoding but it is the empty string,
99 - // still leave it as JSON.
100 - req.SetOption(cmds.EncShort, previousUserProvidedEncoding)
89 + go func() {
90 + httpRes, err := http.DefaultClient.Do(httpReq)
91 + if err != nil {
92 + ec <- err
93 + return
94 + }
95 + // using the overridden JSON encoding in request
96 + res, err := getResponse(httpRes, req)
97 + if err != nil {
98 + ec <- err
99 + return
100 + }
101 + rc <- res
102 + }()
103 +
104 + for {
105 + select {
106 + case <-dc:
107 + log.Debug("Context cancelled, cancelling HTTP request...")
108 + tr := http.DefaultTransport.(*http.Transport)
109 + tr.CancelRequest(httpReq)
110 + dc = nil // Wait for ec or rc
111 + case err := <-ec:
112 + return nil, err
113 + case res := <-rc:
114 + if found && len(previousUserProvidedEncoding) > 0 {
115 + // reset to user provided encoding after sending request
116 + // NB: if user has provided an encoding but it is the empty string,
117 + // still leave it as JSON.
118 + req.SetOption(cmds.EncShort, previousUserProvidedEncoding)
119 + }
120 + return res, nil
121 + }
122 }
102 -
103 - return res, nil
123 }
124
125 func getQuery(req cmds.Request) (string, error) {