[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()
+}