client: ensure Response closed on cancel
parent
b41d6bc416
commit
25cf916a80
|
@ -270,9 +270,10 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon
|
||||||
case rtresp := <-rtchan:
|
case rtresp := <-rtchan:
|
||||||
resp, err = rtresp.resp, rtresp.err
|
resp, err = rtresp.resp, rtresp.err
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
// cancel and wait for request to actually exit before continuing
|
||||||
c.transport.CancelRequest(req)
|
c.transport.CancelRequest(req)
|
||||||
// wait for request to actually exit before continuing
|
rtresp := <-rtchan
|
||||||
<-rtchan
|
resp = rtresp.resp
|
||||||
err = ctx.Err()
|
err = ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -179,6 +180,44 @@ func TestSimpleHTTPClientDoCancelContext(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type checkableReadCloser struct {
|
||||||
|
io.ReadCloser
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *checkableReadCloser) Close() error {
|
||||||
|
c.closed = true
|
||||||
|
return c.ReadCloser.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSimpleHTTPClientDoCancelContextResponseBodyClosed(t *testing.T) {
|
||||||
|
tr := newFakeTransport()
|
||||||
|
c := &simpleHTTPClient{transport: tr}
|
||||||
|
|
||||||
|
// create an already-cancelled context
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
body := &checkableReadCloser{ReadCloser: ioutil.NopCloser(strings.NewReader("foo"))}
|
||||||
|
go func() {
|
||||||
|
// wait for CancelRequest to be called, informing us that simpleHTTPClient
|
||||||
|
// knows the context is already timed out
|
||||||
|
<-tr.startCancel
|
||||||
|
|
||||||
|
tr.respchan <- &http.Response{Body: body}
|
||||||
|
tr.finishCancel <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, _, err := c.Do(ctx, &fakeAction{})
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected non-nil error, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !body.closed {
|
||||||
|
t.Fatalf("expected closed body")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSimpleHTTPClientDoCancelContextWaitForRoundTrip(t *testing.T) {
|
func TestSimpleHTTPClientDoCancelContextWaitForRoundTrip(t *testing.T) {
|
||||||
tr := newFakeTransport()
|
tr := newFakeTransport()
|
||||||
c := &simpleHTTPClient{transport: tr}
|
c := &simpleHTTPClient{transport: tr}
|
||||||
|
|
Loading…
Reference in New Issue