-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcancelreader.go
36 lines (30 loc) · 928 Bytes
/
cancelreader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package retryhttp
import (
"context"
"io"
"net/http"
)
// If a request's context is canceled before the response's body is read, the byte stream
// will be reclaimed by the runtime. This results in a race against the runtime to read
// the body and often ends in an error. Instead of canceling the context before returning
// a response out, the cancel call is delayed until Close is called on the response body.
// The response body is replaced with this struct to facilitate this.
// This solution is based on https://github.com/go-kit/kit/issues/773.
type cancelReader struct {
io.ReadCloser
cancel context.CancelFunc
}
func (cr cancelReader) Close() error {
cr.cancel()
return cr.ReadCloser.Close()
}
func injectCancelReader(res *http.Response, cancel context.CancelFunc) *http.Response {
if res == nil {
return nil
}
res.Body = cancelReader{
ReadCloser: res.Body,
cancel: cancel,
}
return res
}