Skip to content

Commit 52ce05b

Browse files
net/http: use cancelKey to cancel request
Follows up on CL 245357 and adds missing returns in waitCondition (CL 477196) Fixes #51354
1 parent ed8cbaf commit 52ce05b

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

src/net/http/transport.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2248,7 +2248,7 @@ func (pc *persistConn) readLoop() {
22482248
}
22492249
case <-rc.req.Cancel:
22502250
alive = false
2251-
pc.t.CancelRequest(rc.req)
2251+
pc.t.cancelRequest(rc.cancelKey, errRequestCanceled)
22522252
case <-rc.req.Context().Done():
22532253
alive = false
22542254
pc.t.cancelRequest(rc.cancelKey, rc.req.Context().Err())

src/net/http/transport_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,7 @@ func testTransportCancelRequest(t *testing.T, mode testMode) {
24402440
if d > 0 {
24412441
t.Logf("pending requests = %d after %v (want 0)", n, d)
24422442
}
2443+
return false
24432444
}
24442445
return true
24452446
})
@@ -2599,6 +2600,65 @@ func testCancelRequestWithChannel(t *testing.T, mode testMode) {
25992600
if d > 0 {
26002601
t.Logf("pending requests = %d after %v (want 0)", n, d)
26012602
}
2603+
return false
2604+
}
2605+
return true
2606+
})
2607+
}
2608+
2609+
// Issue 51354
2610+
func TestCancelRequestWithBodyWithChannel(t *testing.T) {
2611+
run(t, testCancelRequestWithBodyWithChannel, []testMode{http1Mode})
2612+
}
2613+
func testCancelRequestWithBodyWithChannel(t *testing.T, mode testMode) {
2614+
if testing.Short() {
2615+
t.Skip("skipping test in -short mode")
2616+
}
2617+
2618+
const msg = "Hello"
2619+
unblockc := make(chan struct{})
2620+
ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
2621+
io.WriteString(w, msg)
2622+
w.(Flusher).Flush() // send headers and some body
2623+
<-unblockc
2624+
})).ts
2625+
defer close(unblockc)
2626+
2627+
c := ts.Client()
2628+
tr := c.Transport.(*Transport)
2629+
2630+
req, _ := NewRequest("POST", ts.URL, strings.NewReader("withbody"))
2631+
cancel := make(chan struct{})
2632+
req.Cancel = cancel
2633+
2634+
res, err := c.Do(req)
2635+
if err != nil {
2636+
t.Fatal(err)
2637+
}
2638+
body := make([]byte, len(msg))
2639+
n, _ := io.ReadFull(res.Body, body)
2640+
if n != len(body) || !bytes.Equal(body, []byte(msg)) {
2641+
t.Errorf("Body = %q; want %q", body[:n], msg)
2642+
}
2643+
close(cancel)
2644+
2645+
tail, err := io.ReadAll(res.Body)
2646+
res.Body.Close()
2647+
if err != ExportErrRequestCanceled {
2648+
t.Errorf("Body.Read error = %v; want errRequestCanceled", err)
2649+
} else if len(tail) > 0 {
2650+
t.Errorf("Spurious bytes from Body.Read: %q", tail)
2651+
}
2652+
2653+
// Verify no outstanding requests after readLoop/writeLoop
2654+
// goroutines shut down.
2655+
waitCondition(t, 10*time.Millisecond, func(d time.Duration) bool {
2656+
n := tr.NumPendingRequestsForTesting()
2657+
if n > 0 {
2658+
if d > 0 {
2659+
t.Logf("pending requests = %d after %v (want 0)", n, d)
2660+
}
2661+
return false
26022662
}
26032663
return true
26042664
})

0 commit comments

Comments
 (0)