@@ -474,6 +474,56 @@ func testTransportReadToEndReusesConn(t *testing.T, mode testMode) {
474474 }
475475}
476476
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 + path )
499+ if err != nil {
500+ t .Errorf ("Get %s: %v" , path , err )
501+ continue
502+ }
503+
504+ if res .ContentLength != int64 (wantLen ) {
505+ t .Errorf ("%s res.ContentLength = %d; want %d" , path , 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 ("%s ReadAll(Body) = %q, %v; want %q, nil" , path , string (got ), err , msg )
518+ }
519+ }
520+ }
521+
522+ if len (addrSeen ) != 1 {
523+ t .Errorf ("for %s, server saw %d distinct client addresses; want 1" , path , len (addrSeen ))
524+ }
525+ }
526+
477527func TestTransportMaxPerHostIdleConns (t * testing.T ) {
478528 run (t , testTransportMaxPerHostIdleConns , []testMode {http1Mode })
479529}
0 commit comments