Skip to content

Commit

Permalink
http2: send a nil error if we cancel a delayed body write
Browse files Browse the repository at this point in the history
Once a request body is scheduled to be written, a result of the write is always
expected. If the body writer is cancelled, and the write was never started,
send a successful result.

The test included is a modified version of the TestNoSniffExpectRequestBody_h2 found
in net/http.

Updates golang/go#42498

Change-Id: If3f23993170bdf10e9ae4244ec13ae269bd3877a
Reviewed-on: https://go-review.googlesource.com/c/net/+/269058
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
  • Loading branch information
fraenkel authored and bradfitz committed Dec 1, 2020
1 parent 69a7880 commit 5d6afe9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
4 changes: 3 additions & 1 deletion http2/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -2632,7 +2632,9 @@ func (t *Transport) getBodyWriterState(cs *clientStream, body io.Reader) (s body

func (s bodyWriterState) cancel() {
if s.timer != nil {
s.timer.Stop()
if s.timer.Stop() {
s.resc <- nil
}
}
}

Expand Down
36 changes: 36 additions & 0 deletions http2/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4882,3 +4882,39 @@ func TestTransportBodyRewindRace(t *testing.T) {

wg.Wait()
}

// Issue 42498: A request with a body will never be sent if the stream is
// reset prior to sending any data.
func TestTransportServerResetStreamAtHeaders(t *testing.T) {
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
return
}, optOnlyServer)
defer st.Close()

tr := &http.Transport{
TLSClientConfig: tlsConfigInsecure,
MaxConnsPerHost: 1,
ExpectContinueTimeout: 10 * time.Second,
}

err := ConfigureTransport(tr)
if err != nil {
t.Fatal(err)
}
client := &http.Client{
Transport: tr,
}

req, err := http.NewRequest("POST", st.ts.URL, errorReader{io.EOF})
if err != nil {
t.Fatalf("unexpect new request error: %v", err)
}
req.ContentLength = 0 // so transport is tempted to sniff it
req.Header.Set("Expect", "100-continue")
res, err := client.Do(req)
if err != nil {
t.Fatal(err)
}
res.Body.Close()
}

0 comments on commit 5d6afe9

Please sign in to comment.