@@ -474,6 +474,56 @@ func testTransportReadToEndReusesConn(t *testing.T, mode testMode) {
474
474
}
475
475
}
476
476
477
+ // Tests that the HTTP transport re-uses connections when a client
478
+ // early closes a response Body but the content is fully read into the underlying
479
+ // buffer. So we can discard the body buffer and reuse the connection.
480
+ func TestTransportReusesEarlyCloseButAllReceivedConn (t * testing.T ) {
481
+ run (t , testTransportReusesEarlyCloseButAllReceivedConn )
482
+ }
483
+ func testTransportReusesEarlyCloseButAllReceivedConn (t * testing.T , mode testMode ) {
484
+ const msg = "foobar"
485
+
486
+ var addrSeen map [string ]int
487
+ ts := newClientServerTest (t , mode , HandlerFunc (func (w ResponseWriter , r * Request ) {
488
+ addrSeen [r .RemoteAddr ]++
489
+ w .Header ().Set ("Content-Length" , strconv .Itoa (len (msg )))
490
+ w .WriteHeader (200 )
491
+ w .Write ([]byte (msg ))
492
+ })).ts
493
+
494
+ wantLen := len (msg )
495
+ addrSeen = make (map [string ]int )
496
+ total := 5
497
+ for i := 0 ; i < total ; i ++ {
498
+ res , err := ts .Client ().Get (ts .URL )
499
+ if err != nil {
500
+ t .Errorf ("Get /: %v" , err )
501
+ continue
502
+ }
503
+
504
+ if res .ContentLength != int64 (wantLen ) {
505
+ t .Errorf ("res.ContentLength = %d; want %d" , res .ContentLength , wantLen )
506
+ }
507
+
508
+ if i + 1 < total {
509
+ // Close body directly. The body is small enough, so probably the underlying bufio.Reader
510
+ // has read entire body into buffer. Thus even if the body is not read, the buffer is discarded
511
+ // then connection is reused.
512
+ res .Body .Close ()
513
+ } else {
514
+ // when reading body, everything should be same.
515
+ got , err := io .ReadAll (res .Body )
516
+ if string (got ) != msg || err != nil {
517
+ t .Errorf ("ReadAll(Body) = %q, %v; want %q, nil" , string (got ), err , msg )
518
+ }
519
+ }
520
+ }
521
+
522
+ if len (addrSeen ) != 1 {
523
+ t .Errorf ("server saw %d distinct client addresses; want 1" , len (addrSeen ))
524
+ }
525
+ }
526
+
477
527
func TestTransportMaxPerHostIdleConns (t * testing.T ) {
478
528
run (t , testTransportMaxPerHostIdleConns , []testMode {http1Mode })
479
529
}
0 commit comments