Commit 78c4dc37 authored by Luan Santos's avatar Luan Santos Committed by Tom Bergan

net/http: allow reuse of http.Request objects

Calling response.Body.Close() early would generarate a race before this.
Since closing would return early before the main code path had a chance
to reset the request canceler. Having a non-nil request canceler at the
start of the next request would cause a "request canceled" error.

Here we simply wait for the eofc channel to be closed before returning
from earlyCloseFn, ensuring that the caller won't be re-using that
Request object before we have a chance to reset the request canceler to
nil.

Fixes #21838

Change-Id: I641815526c6ac63d1816c9b6ad49d73715f7a5cb
Reviewed-on: https://go-review.googlesource.com/62891
Run-TryBot: Tom Bergan <tombergan@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarTom Bergan <tombergan@google.com>
parent cf872fae
......@@ -1616,6 +1616,7 @@ func (pc *persistConn) readLoop() {
body: resp.Body,
earlyCloseFn: func() error {
waitForBodyRead <- false
<-eofc // will be closed by deferred call at the end of the function
return nil
},
......
......@@ -124,6 +124,34 @@ func (tcs *testConnSet) check(t *testing.T) {
}
}
func TestReuseRequest(t *testing.T) {
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Write([]byte("{}"))
}))
defer ts.Close()
c := ts.Client()
req, _ := NewRequest("GET", ts.URL, nil)
res, err := c.Do(req)
if err != nil {
t.Fatal(err)
}
err = res.Body.Close()
if err != nil {
t.Fatal(err)
}
res, err = c.Do(req)
if err != nil {
t.Fatal(err)
}
err = res.Body.Close()
if err != nil {
t.Fatal(err)
}
}
// Two subsequent requests and verify their response is the same.
// The response from the server is our own IP:port
func TestTransportKeepAlives(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment