author | Brad Fitzpatrick
<bradfitz@golang.org> 2016-09-12 14:44:02 UTC |
committer | Brad Fitzpatrick
<bradfitz@golang.org> 2016-09-12 18:43:37 UTC |
parent | 57c782092076593634268e699ced8fd6360dbb25 |
http2/transport.go | +3 | -3 |
http2/transport_test.go | +21 | -0 |
diff --git a/http2/transport.go b/http2/transport.go index 7a8563d..42c73bd 100644 --- a/http2/transport.go +++ b/http2/transport.go @@ -656,9 +656,6 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { } hasTrailers := trailers != "" - body, contentLen := bodyAndLength(req) - hasBody := body != nil - cc.mu.Lock() cc.lastActive = time.Now() if cc.closed || !cc.canTakeNewRequestLocked() { @@ -666,6 +663,9 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { return nil, errClientConnUnusable } + body, contentLen := bodyAndLength(req) + hasBody := body != nil + // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? var requestedGzip bool if !cc.t.disableCompression() && diff --git a/http2/transport_test.go b/http2/transport_test.go index e220c91..96d0a08 100644 --- a/http2/transport_test.go +++ b/http2/transport_test.go @@ -2597,3 +2597,24 @@ func TestTransportRequestPathPseudo(t *testing.T) { } } + +// golang.org/issue/17071 -- don't sniff the first byte of the request body +// before we've determined that the ClientConn is usable. +func TestRoundTripDoesntConsumeRequestBodyEarly(t *testing.T) { + const body = "foo" + req, _ := http.NewRequest("POST", "http://foo.com/", ioutil.NopCloser(strings.NewReader(body))) + cc := &ClientConn{ + closed: true, + } + _, err := cc.RoundTrip(req) + if err != errClientConnUnusable { + t.Fatalf("RoundTrip = %v; want errClientConnUnusable", err) + } + slurp, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Errorf("ReadAll = %v", err) + } + if string(slurp) != body { + t.Errorf("Body = %q; want %q", slurp, body) + } +}