[release-branch.go1.14] http2: send a nil error if we cancel a delayed body write
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#42586
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>
(cherry picked from commit 5d6afe98e0b7d884bea12f3ab4e7f8c1a07ce5c8)
Reviewed-on: https://go-review.googlesource.com/c/net/+/288114
Trust: Damien Neil <dneil@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/http2/transport.go b/http2/transport.go
index 80cff2a..86dd4c8 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -2560,7 +2560,9 @@
func (s bodyWriterState) cancel() {
if s.timer != nil {
- s.timer.Stop()
+ if s.timer.Stop() {
+ s.resc <- nil
+ }
}
}
diff --git a/http2/transport_test.go b/http2/transport_test.go
index d0d0542..c7826b3 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -4628,3 +4628,39 @@
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()
+}