github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/net/http/transport_test.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Tests for transport.go.
     6  //
     7  // More tests are in clientserver_test.go (for things testing both client & server for both
     8  // HTTP/1 and HTTP/2). This
     9  
    10  package http_test
    11  
    12  import (
    13  	"bufio"
    14  	"bytes"
    15  	"compress/gzip"
    16  	"context"
    17  	"crypto/rand"
    18  	"crypto/tls"
    19  	"crypto/x509"
    20  	"encoding/binary"
    21  	"errors"
    22  	"fmt"
    23  	"go/token"
    24  	"internal/nettrace"
    25  	"io"
    26  	"log"
    27  	mrand "math/rand"
    28  	"net"
    29  	. "net/http"
    30  	"net/http/httptest"
    31  	"net/http/httptrace"
    32  	"net/http/httputil"
    33  	"github.com/mtsmfm/go/src/net/http/internal/testcert"
    34  	"net/textproto"
    35  	"net/url"
    36  	"os"
    37  	"reflect"
    38  	"runtime"
    39  	"strconv"
    40  	"strings"
    41  	"sync"
    42  	"sync/atomic"
    43  	"testing"
    44  	"testing/iotest"
    45  	"time"
    46  
    47  	"golang.org/x/net/http/httpguts"
    48  )
    49  
    50  // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
    51  // and then verify that the final 2 responses get errors back.
    52  
    53  // hostPortHandler writes back the client's "host:port".
    54  var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
    55  	if r.FormValue("close") == "true" {
    56  		w.Header().Set("Connection", "close")
    57  	}
    58  	w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close))
    59  	w.Write([]byte(r.RemoteAddr))
    60  
    61  	// Include the address of the net.Conn in addition to the RemoteAddr,
    62  	// in case kernels reuse source ports quickly (see Issue 52450)
    63  	if c, ok := ResponseWriterConnForTesting(w); ok {
    64  		fmt.Fprintf(w, ", %T %p", c, c)
    65  	}
    66  })
    67  
    68  // testCloseConn is a net.Conn tracked by a testConnSet.
    69  type testCloseConn struct {
    70  	net.Conn
    71  	set *testConnSet
    72  }
    73  
    74  func (c *testCloseConn) Close() error {
    75  	c.set.remove(c)
    76  	return c.Conn.Close()
    77  }
    78  
    79  // testConnSet tracks a set of TCP connections and whether they've
    80  // been closed.
    81  type testConnSet struct {
    82  	t      *testing.T
    83  	mu     sync.Mutex // guards closed and list
    84  	closed map[net.Conn]bool
    85  	list   []net.Conn // in order created
    86  }
    87  
    88  func (tcs *testConnSet) insert(c net.Conn) {
    89  	tcs.mu.Lock()
    90  	defer tcs.mu.Unlock()
    91  	tcs.closed[c] = false
    92  	tcs.list = append(tcs.list, c)
    93  }
    94  
    95  func (tcs *testConnSet) remove(c net.Conn) {
    96  	tcs.mu.Lock()
    97  	defer tcs.mu.Unlock()
    98  	tcs.closed[c] = true
    99  }
   100  
   101  // some tests use this to manage raw tcp connections for later inspection
   102  func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
   103  	connSet := &testConnSet{
   104  		t:      t,
   105  		closed: make(map[net.Conn]bool),
   106  	}
   107  	dial := func(n, addr string) (net.Conn, error) {
   108  		c, err := net.Dial(n, addr)
   109  		if err != nil {
   110  			return nil, err
   111  		}
   112  		tc := &testCloseConn{c, connSet}
   113  		connSet.insert(tc)
   114  		return tc, nil
   115  	}
   116  	return connSet, dial
   117  }
   118  
   119  func (tcs *testConnSet) check(t *testing.T) {
   120  	tcs.mu.Lock()
   121  	defer tcs.mu.Unlock()
   122  	for i := 4; i >= 0; i-- {
   123  		for i, c := range tcs.list {
   124  			if tcs.closed[c] {
   125  				continue
   126  			}
   127  			if i != 0 {
   128  				tcs.mu.Unlock()
   129  				time.Sleep(50 * time.Millisecond)
   130  				tcs.mu.Lock()
   131  				continue
   132  			}
   133  			t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
   134  		}
   135  	}
   136  }
   137  
   138  func TestReuseRequest(t *testing.T) { run(t, testReuseRequest) }
   139  func testReuseRequest(t *testing.T, mode testMode) {
   140  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   141  		w.Write([]byte("{}"))
   142  	})).ts
   143  
   144  	c := ts.Client()
   145  	req, _ := NewRequest("GET", ts.URL, nil)
   146  	res, err := c.Do(req)
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	err = res.Body.Close()
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  
   155  	res, err = c.Do(req)
   156  	if err != nil {
   157  		t.Fatal(err)
   158  	}
   159  	err = res.Body.Close()
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  }
   164  
   165  // Two subsequent requests and verify their response is the same.
   166  // The response from the server is our own IP:port
   167  func TestTransportKeepAlives(t *testing.T) { run(t, testTransportKeepAlives, []testMode{http1Mode}) }
   168  func testTransportKeepAlives(t *testing.T, mode testMode) {
   169  	ts := newClientServerTest(t, mode, hostPortHandler).ts
   170  
   171  	c := ts.Client()
   172  	for _, disableKeepAlive := range []bool{false, true} {
   173  		c.Transport.(*Transport).DisableKeepAlives = disableKeepAlive
   174  		fetch := func(n int) string {
   175  			res, err := c.Get(ts.URL)
   176  			if err != nil {
   177  				t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
   178  			}
   179  			body, err := io.ReadAll(res.Body)
   180  			if err != nil {
   181  				t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
   182  			}
   183  			return string(body)
   184  		}
   185  
   186  		body1 := fetch(1)
   187  		body2 := fetch(2)
   188  
   189  		bodiesDiffer := body1 != body2
   190  		if bodiesDiffer != disableKeepAlive {
   191  			t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
   192  				disableKeepAlive, bodiesDiffer, body1, body2)
   193  		}
   194  	}
   195  }
   196  
   197  func TestTransportConnectionCloseOnResponse(t *testing.T) {
   198  	run(t, testTransportConnectionCloseOnResponse)
   199  }
   200  func testTransportConnectionCloseOnResponse(t *testing.T, mode testMode) {
   201  	ts := newClientServerTest(t, mode, hostPortHandler).ts
   202  
   203  	connSet, testDial := makeTestDial(t)
   204  
   205  	c := ts.Client()
   206  	tr := c.Transport.(*Transport)
   207  	tr.Dial = testDial
   208  
   209  	for _, connectionClose := range []bool{false, true} {
   210  		fetch := func(n int) string {
   211  			req := new(Request)
   212  			var err error
   213  			req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose))
   214  			if err != nil {
   215  				t.Fatalf("URL parse error: %v", err)
   216  			}
   217  			req.Method = "GET"
   218  			req.Proto = "HTTP/1.1"
   219  			req.ProtoMajor = 1
   220  			req.ProtoMinor = 1
   221  
   222  			res, err := c.Do(req)
   223  			if err != nil {
   224  				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
   225  			}
   226  			defer res.Body.Close()
   227  			body, err := io.ReadAll(res.Body)
   228  			if err != nil {
   229  				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
   230  			}
   231  			return string(body)
   232  		}
   233  
   234  		body1 := fetch(1)
   235  		body2 := fetch(2)
   236  		bodiesDiffer := body1 != body2
   237  		if bodiesDiffer != connectionClose {
   238  			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
   239  				connectionClose, bodiesDiffer, body1, body2)
   240  		}
   241  
   242  		tr.CloseIdleConnections()
   243  	}
   244  
   245  	connSet.check(t)
   246  }
   247  
   248  // TestTransportConnectionCloseOnRequest tests that the Transport's doesn't reuse
   249  // an underlying TCP connection after making an http.Request with Request.Close set.
   250  //
   251  // It tests the behavior by making an HTTP request to a server which
   252  // describes the source source connection it got (remote port number +
   253  // address of its net.Conn).
   254  func TestTransportConnectionCloseOnRequest(t *testing.T) {
   255  	run(t, testTransportConnectionCloseOnRequest, []testMode{http1Mode})
   256  }
   257  func testTransportConnectionCloseOnRequest(t *testing.T, mode testMode) {
   258  	ts := newClientServerTest(t, mode, hostPortHandler).ts
   259  
   260  	connSet, testDial := makeTestDial(t)
   261  
   262  	c := ts.Client()
   263  	tr := c.Transport.(*Transport)
   264  	tr.Dial = testDial
   265  	for _, reqClose := range []bool{false, true} {
   266  		fetch := func(n int) string {
   267  			req := new(Request)
   268  			var err error
   269  			req.URL, err = url.Parse(ts.URL)
   270  			if err != nil {
   271  				t.Fatalf("URL parse error: %v", err)
   272  			}
   273  			req.Method = "GET"
   274  			req.Proto = "HTTP/1.1"
   275  			req.ProtoMajor = 1
   276  			req.ProtoMinor = 1
   277  			req.Close = reqClose
   278  
   279  			res, err := c.Do(req)
   280  			if err != nil {
   281  				t.Fatalf("error in Request.Close=%v, req #%d, Do: %v", reqClose, n, err)
   282  			}
   283  			if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(reqClose); got != want {
   284  				t.Errorf("for Request.Close = %v; handler's X-Saw-Close was %v; want %v",
   285  					reqClose, got, !reqClose)
   286  			}
   287  			body, err := io.ReadAll(res.Body)
   288  			if err != nil {
   289  				t.Fatalf("for Request.Close=%v, on request %v/2: ReadAll: %v", reqClose, n, err)
   290  			}
   291  			return string(body)
   292  		}
   293  
   294  		body1 := fetch(1)
   295  		body2 := fetch(2)
   296  
   297  		got := 1
   298  		if body1 != body2 {
   299  			got++
   300  		}
   301  		want := 1
   302  		if reqClose {
   303  			want = 2
   304  		}
   305  		if got != want {
   306  			t.Errorf("for Request.Close=%v: server saw %v unique connections, wanted %v\n\nbodies were: %q and %q",
   307  				reqClose, got, want, body1, body2)
   308  		}
   309  
   310  		tr.CloseIdleConnections()
   311  	}
   312  
   313  	connSet.check(t)
   314  }
   315  
   316  // if the Transport's DisableKeepAlives is set, all requests should
   317  // send Connection: close.
   318  // HTTP/1-only (Connection: close doesn't exist in h2)
   319  func TestTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T) {
   320  	run(t, testTransportConnectionCloseOnRequestDisableKeepAlive, []testMode{http1Mode})
   321  }
   322  func testTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T, mode testMode) {
   323  	ts := newClientServerTest(t, mode, hostPortHandler).ts
   324  
   325  	c := ts.Client()
   326  	c.Transport.(*Transport).DisableKeepAlives = true
   327  
   328  	res, err := c.Get(ts.URL)
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  	res.Body.Close()
   333  	if res.Header.Get("X-Saw-Close") != "true" {
   334  		t.Errorf("handler didn't see Connection: close ")
   335  	}
   336  }
   337  
   338  // Test that Transport only sends one "Connection: close", regardless of
   339  // how "close" was indicated.
   340  func TestTransportRespectRequestWantsClose(t *testing.T) {
   341  	run(t, testTransportRespectRequestWantsClose, []testMode{http1Mode})
   342  }
   343  func testTransportRespectRequestWantsClose(t *testing.T, mode testMode) {
   344  	tests := []struct {
   345  		disableKeepAlives bool
   346  		close             bool
   347  	}{
   348  		{disableKeepAlives: false, close: false},
   349  		{disableKeepAlives: false, close: true},
   350  		{disableKeepAlives: true, close: false},
   351  		{disableKeepAlives: true, close: true},
   352  	}
   353  
   354  	for _, tc := range tests {
   355  		t.Run(fmt.Sprintf("DisableKeepAlive=%v,RequestClose=%v", tc.disableKeepAlives, tc.close),
   356  			func(t *testing.T) {
   357  				ts := newClientServerTest(t, mode, hostPortHandler).ts
   358  
   359  				c := ts.Client()
   360  				c.Transport.(*Transport).DisableKeepAlives = tc.disableKeepAlives
   361  				req, err := NewRequest("GET", ts.URL, nil)
   362  				if err != nil {
   363  					t.Fatal(err)
   364  				}
   365  				count := 0
   366  				trace := &httptrace.ClientTrace{
   367  					WroteHeaderField: func(key string, field []string) {
   368  						if key != "Connection" {
   369  							return
   370  						}
   371  						if httpguts.HeaderValuesContainsToken(field, "close") {
   372  							count += 1
   373  						}
   374  					},
   375  				}
   376  				req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
   377  				req.Close = tc.close
   378  				res, err := c.Do(req)
   379  				if err != nil {
   380  					t.Fatal(err)
   381  				}
   382  				defer res.Body.Close()
   383  				if want := tc.disableKeepAlives || tc.close; count > 1 || (count == 1) != want {
   384  					t.Errorf("expecting want:%v, got 'Connection: close':%d", want, count)
   385  				}
   386  			})
   387  	}
   388  
   389  }
   390  
   391  func TestTransportIdleCacheKeys(t *testing.T) {
   392  	run(t, testTransportIdleCacheKeys, []testMode{http1Mode})
   393  }
   394  func testTransportIdleCacheKeys(t *testing.T, mode testMode) {
   395  	ts := newClientServerTest(t, mode, hostPortHandler).ts
   396  	c := ts.Client()
   397  	tr := c.Transport.(*Transport)
   398  
   399  	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
   400  		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
   401  	}
   402  
   403  	resp, err := c.Get(ts.URL)
   404  	if err != nil {
   405  		t.Error(err)
   406  	}
   407  	io.ReadAll(resp.Body)
   408  
   409  	keys := tr.IdleConnKeysForTesting()
   410  	if e, g := 1, len(keys); e != g {
   411  		t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g)
   412  	}
   413  
   414  	if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
   415  		t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
   416  	}
   417  
   418  	tr.CloseIdleConnections()
   419  	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
   420  		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
   421  	}
   422  }
   423  
   424  // Tests that the HTTP transport re-uses connections when a client
   425  // reads to the end of a response Body without closing it.
   426  func TestTransportReadToEndReusesConn(t *testing.T) { run(t, testTransportReadToEndReusesConn) }
   427  func testTransportReadToEndReusesConn(t *testing.T, mode testMode) {
   428  	const msg = "foobar"
   429  
   430  	var addrSeen map[string]int
   431  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   432  		addrSeen[r.RemoteAddr]++
   433  		if r.URL.Path == "/chunked/" {
   434  			w.WriteHeader(200)
   435  			w.(Flusher).Flush()
   436  		} else {
   437  			w.Header().Set("Content-Length", strconv.Itoa(len(msg)))
   438  			w.WriteHeader(200)
   439  		}
   440  		w.Write([]byte(msg))
   441  	})).ts
   442  
   443  	for pi, path := range []string{"/content-length/", "/chunked/"} {
   444  		wantLen := []int{len(msg), -1}[pi]
   445  		addrSeen = make(map[string]int)
   446  		for i := 0; i < 3; i++ {
   447  			res, err := ts.Client().Get(ts.URL + path)
   448  			if err != nil {
   449  				t.Errorf("Get %s: %v", path, err)
   450  				continue
   451  			}
   452  			// We want to close this body eventually (before the
   453  			// defer afterTest at top runs), but not before the
   454  			// len(addrSeen) check at the bottom of this test,
   455  			// since Closing this early in the loop would risk
   456  			// making connections be re-used for the wrong reason.
   457  			defer res.Body.Close()
   458  
   459  			if res.ContentLength != int64(wantLen) {
   460  				t.Errorf("%s res.ContentLength = %d; want %d", path, res.ContentLength, wantLen)
   461  			}
   462  			got, err := io.ReadAll(res.Body)
   463  			if string(got) != msg || err != nil {
   464  				t.Errorf("%s ReadAll(Body) = %q, %v; want %q, nil", path, string(got), err, msg)
   465  			}
   466  		}
   467  		if len(addrSeen) != 1 {
   468  			t.Errorf("for %s, server saw %d distinct client addresses; want 1", path, len(addrSeen))
   469  		}
   470  	}
   471  }
   472  
   473  func TestTransportMaxPerHostIdleConns(t *testing.T) {
   474  	run(t, testTransportMaxPerHostIdleConns, []testMode{http1Mode})
   475  }
   476  func testTransportMaxPerHostIdleConns(t *testing.T, mode testMode) {
   477  	stop := make(chan struct{}) // stop marks the exit of main Test goroutine
   478  	defer close(stop)
   479  
   480  	resch := make(chan string)
   481  	gotReq := make(chan bool)
   482  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   483  		gotReq <- true
   484  		var msg string
   485  		select {
   486  		case <-stop:
   487  			return
   488  		case msg = <-resch:
   489  		}
   490  		_, err := w.Write([]byte(msg))
   491  		if err != nil {
   492  			t.Errorf("Write: %v", err)
   493  			return
   494  		}
   495  	})).ts
   496  
   497  	c := ts.Client()
   498  	tr := c.Transport.(*Transport)
   499  	maxIdleConnsPerHost := 2
   500  	tr.MaxIdleConnsPerHost = maxIdleConnsPerHost
   501  
   502  	// Start 3 outstanding requests and wait for the server to get them.
   503  	// Their responses will hang until we write to resch, though.
   504  	donech := make(chan bool)
   505  	doReq := func() {
   506  		defer func() {
   507  			select {
   508  			case <-stop:
   509  				return
   510  			case donech <- t.Failed():
   511  			}
   512  		}()
   513  		resp, err := c.Get(ts.URL)
   514  		if err != nil {
   515  			t.Error(err)
   516  			return
   517  		}
   518  		if _, err := io.ReadAll(resp.Body); err != nil {
   519  			t.Errorf("ReadAll: %v", err)
   520  			return
   521  		}
   522  	}
   523  	go doReq()
   524  	<-gotReq
   525  	go doReq()
   526  	<-gotReq
   527  	go doReq()
   528  	<-gotReq
   529  
   530  	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
   531  		t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
   532  	}
   533  
   534  	resch <- "res1"
   535  	<-donech
   536  	keys := tr.IdleConnKeysForTesting()
   537  	if e, g := 1, len(keys); e != g {
   538  		t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
   539  	}
   540  	addr := ts.Listener.Addr().String()
   541  	cacheKey := "|http|" + addr
   542  	if keys[0] != cacheKey {
   543  		t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
   544  	}
   545  	if e, g := 1, tr.IdleConnCountForTesting("http", addr); e != g {
   546  		t.Errorf("after first response, expected %d idle conns; got %d", e, g)
   547  	}
   548  
   549  	resch <- "res2"
   550  	<-donech
   551  	if g, w := tr.IdleConnCountForTesting("http", addr), 2; g != w {
   552  		t.Errorf("after second response, idle conns = %d; want %d", g, w)
   553  	}
   554  
   555  	resch <- "res3"
   556  	<-donech
   557  	if g, w := tr.IdleConnCountForTesting("http", addr), maxIdleConnsPerHost; g != w {
   558  		t.Errorf("after third response, idle conns = %d; want %d", g, w)
   559  	}
   560  }
   561  
   562  func TestTransportMaxConnsPerHostIncludeDialInProgress(t *testing.T) {
   563  	run(t, testTransportMaxConnsPerHostIncludeDialInProgress)
   564  }
   565  func testTransportMaxConnsPerHostIncludeDialInProgress(t *testing.T, mode testMode) {
   566  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   567  		_, err := w.Write([]byte("foo"))
   568  		if err != nil {
   569  			t.Fatalf("Write: %v", err)
   570  		}
   571  	})).ts
   572  	c := ts.Client()
   573  	tr := c.Transport.(*Transport)
   574  	dialStarted := make(chan struct{})
   575  	stallDial := make(chan struct{})
   576  	tr.Dial = func(network, addr string) (net.Conn, error) {
   577  		dialStarted <- struct{}{}
   578  		<-stallDial
   579  		return net.Dial(network, addr)
   580  	}
   581  
   582  	tr.DisableKeepAlives = true
   583  	tr.MaxConnsPerHost = 1
   584  
   585  	preDial := make(chan struct{})
   586  	reqComplete := make(chan struct{})
   587  	doReq := func(reqId string) {
   588  		req, _ := NewRequest("GET", ts.URL, nil)
   589  		trace := &httptrace.ClientTrace{
   590  			GetConn: func(hostPort string) {
   591  				preDial <- struct{}{}
   592  			},
   593  		}
   594  		req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
   595  		resp, err := tr.RoundTrip(req)
   596  		if err != nil {
   597  			t.Errorf("unexpected error for request %s: %v", reqId, err)
   598  		}
   599  		_, err = io.ReadAll(resp.Body)
   600  		if err != nil {
   601  			t.Errorf("unexpected error for request %s: %v", reqId, err)
   602  		}
   603  		reqComplete <- struct{}{}
   604  	}
   605  	// get req1 to dial-in-progress
   606  	go doReq("req1")
   607  	<-preDial
   608  	<-dialStarted
   609  
   610  	// get req2 to waiting on conns per host to go down below max
   611  	go doReq("req2")
   612  	<-preDial
   613  	select {
   614  	case <-dialStarted:
   615  		t.Error("req2 dial started while req1 dial in progress")
   616  		return
   617  	default:
   618  	}
   619  
   620  	// let req1 complete
   621  	stallDial <- struct{}{}
   622  	<-reqComplete
   623  
   624  	// let req2 complete
   625  	<-dialStarted
   626  	stallDial <- struct{}{}
   627  	<-reqComplete
   628  }
   629  
   630  func TestTransportMaxConnsPerHost(t *testing.T) {
   631  	run(t, testTransportMaxConnsPerHost, []testMode{http1Mode, https1Mode, http2Mode})
   632  }
   633  func testTransportMaxConnsPerHost(t *testing.T, mode testMode) {
   634  	CondSkipHTTP2(t)
   635  
   636  	h := HandlerFunc(func(w ResponseWriter, r *Request) {
   637  		_, err := w.Write([]byte("foo"))
   638  		if err != nil {
   639  			t.Fatalf("Write: %v", err)
   640  		}
   641  	})
   642  
   643  	ts := newClientServerTest(t, mode, h).ts
   644  	c := ts.Client()
   645  	tr := c.Transport.(*Transport)
   646  	tr.MaxConnsPerHost = 1
   647  
   648  	mu := sync.Mutex{}
   649  	var conns []net.Conn
   650  	var dialCnt, gotConnCnt, tlsHandshakeCnt int32
   651  	tr.Dial = func(network, addr string) (net.Conn, error) {
   652  		atomic.AddInt32(&dialCnt, 1)
   653  		c, err := net.Dial(network, addr)
   654  		mu.Lock()
   655  		defer mu.Unlock()
   656  		conns = append(conns, c)
   657  		return c, err
   658  	}
   659  
   660  	doReq := func() {
   661  		trace := &httptrace.ClientTrace{
   662  			GotConn: func(connInfo httptrace.GotConnInfo) {
   663  				if !connInfo.Reused {
   664  					atomic.AddInt32(&gotConnCnt, 1)
   665  				}
   666  			},
   667  			TLSHandshakeStart: func() {
   668  				atomic.AddInt32(&tlsHandshakeCnt, 1)
   669  			},
   670  		}
   671  		req, _ := NewRequest("GET", ts.URL, nil)
   672  		req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
   673  
   674  		resp, err := c.Do(req)
   675  		if err != nil {
   676  			t.Fatalf("request failed: %v", err)
   677  		}
   678  		defer resp.Body.Close()
   679  		_, err = io.ReadAll(resp.Body)
   680  		if err != nil {
   681  			t.Fatalf("read body failed: %v", err)
   682  		}
   683  	}
   684  
   685  	wg := sync.WaitGroup{}
   686  	for i := 0; i < 10; i++ {
   687  		wg.Add(1)
   688  		go func() {
   689  			defer wg.Done()
   690  			doReq()
   691  		}()
   692  	}
   693  	wg.Wait()
   694  
   695  	expected := int32(tr.MaxConnsPerHost)
   696  	if dialCnt != expected {
   697  		t.Errorf("round 1: too many dials: %d != %d", dialCnt, expected)
   698  	}
   699  	if gotConnCnt != expected {
   700  		t.Errorf("round 1: too many get connections: %d != %d", gotConnCnt, expected)
   701  	}
   702  	if ts.TLS != nil && tlsHandshakeCnt != expected {
   703  		t.Errorf("round 1: too many tls handshakes: %d != %d", tlsHandshakeCnt, expected)
   704  	}
   705  
   706  	if t.Failed() {
   707  		t.FailNow()
   708  	}
   709  
   710  	mu.Lock()
   711  	for _, c := range conns {
   712  		c.Close()
   713  	}
   714  	conns = nil
   715  	mu.Unlock()
   716  	tr.CloseIdleConnections()
   717  
   718  	doReq()
   719  	expected++
   720  	if dialCnt != expected {
   721  		t.Errorf("round 2: too many dials: %d", dialCnt)
   722  	}
   723  	if gotConnCnt != expected {
   724  		t.Errorf("round 2: too many get connections: %d != %d", gotConnCnt, expected)
   725  	}
   726  	if ts.TLS != nil && tlsHandshakeCnt != expected {
   727  		t.Errorf("round 2: too many tls handshakes: %d != %d", tlsHandshakeCnt, expected)
   728  	}
   729  }
   730  
   731  func TestTransportRemovesDeadIdleConnections(t *testing.T) {
   732  	run(t, testTransportRemovesDeadIdleConnections, []testMode{http1Mode})
   733  }
   734  func testTransportRemovesDeadIdleConnections(t *testing.T, mode testMode) {
   735  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   736  		io.WriteString(w, r.RemoteAddr)
   737  	})).ts
   738  
   739  	c := ts.Client()
   740  	tr := c.Transport.(*Transport)
   741  
   742  	doReq := func(name string) string {
   743  		// Do a POST instead of a GET to prevent the Transport's
   744  		// idempotent request retry logic from kicking in...
   745  		res, err := c.Post(ts.URL, "", nil)
   746  		if err != nil {
   747  			t.Fatalf("%s: %v", name, err)
   748  		}
   749  		if res.StatusCode != 200 {
   750  			t.Fatalf("%s: %v", name, res.Status)
   751  		}
   752  		defer res.Body.Close()
   753  		slurp, err := io.ReadAll(res.Body)
   754  		if err != nil {
   755  			t.Fatalf("%s: %v", name, err)
   756  		}
   757  		return string(slurp)
   758  	}
   759  
   760  	first := doReq("first")
   761  	keys1 := tr.IdleConnKeysForTesting()
   762  
   763  	ts.CloseClientConnections()
   764  
   765  	var keys2 []string
   766  	if !waitCondition(3*time.Second, 50*time.Millisecond, func() bool {
   767  		keys2 = tr.IdleConnKeysForTesting()
   768  		return len(keys2) == 0
   769  	}) {
   770  		t.Fatalf("Transport didn't notice idle connection's death.\nbefore: %q\n after: %q\n", keys1, keys2)
   771  	}
   772  
   773  	second := doReq("second")
   774  	if first == second {
   775  		t.Errorf("expected a different connection between requests. got %q both times", first)
   776  	}
   777  }
   778  
   779  // Test that the Transport notices when a server hangs up on its
   780  // unexpectedly (a keep-alive connection is closed).
   781  func TestTransportServerClosingUnexpectedly(t *testing.T) {
   782  	run(t, testTransportServerClosingUnexpectedly, []testMode{http1Mode})
   783  }
   784  func testTransportServerClosingUnexpectedly(t *testing.T, mode testMode) {
   785  	ts := newClientServerTest(t, mode, hostPortHandler).ts
   786  	c := ts.Client()
   787  
   788  	fetch := func(n, retries int) string {
   789  		condFatalf := func(format string, arg ...any) {
   790  			if retries <= 0 {
   791  				t.Fatalf(format, arg...)
   792  			}
   793  			t.Logf("retrying shortly after expected error: "+format, arg...)
   794  			time.Sleep(time.Second / time.Duration(retries))
   795  		}
   796  		for retries >= 0 {
   797  			retries--
   798  			res, err := c.Get(ts.URL)
   799  			if err != nil {
   800  				condFatalf("error in req #%d, GET: %v", n, err)
   801  				continue
   802  			}
   803  			body, err := io.ReadAll(res.Body)
   804  			if err != nil {
   805  				condFatalf("error in req #%d, ReadAll: %v", n, err)
   806  				continue
   807  			}
   808  			res.Body.Close()
   809  			return string(body)
   810  		}
   811  		panic("unreachable")
   812  	}
   813  
   814  	body1 := fetch(1, 0)
   815  	body2 := fetch(2, 0)
   816  
   817  	// Close all the idle connections in a way that's similar to
   818  	// the server hanging up on us. We don't use
   819  	// httptest.Server.CloseClientConnections because it's
   820  	// best-effort and stops blocking after 5 seconds. On a loaded
   821  	// machine running many tests concurrently it's possible for
   822  	// that method to be async and cause the body3 fetch below to
   823  	// run on an old connection. This function is synchronous.
   824  	ExportCloseTransportConnsAbruptly(c.Transport.(*Transport))
   825  
   826  	body3 := fetch(3, 5)
   827  
   828  	if body1 != body2 {
   829  		t.Errorf("expected body1 and body2 to be equal")
   830  	}
   831  	if body2 == body3 {
   832  		t.Errorf("expected body2 and body3 to be different")
   833  	}
   834  }
   835  
   836  // Test for https://golang.org/issue/2616 (appropriate issue number)
   837  // This fails pretty reliably with GOMAXPROCS=100 or something high.
   838  func TestStressSurpriseServerCloses(t *testing.T) {
   839  	run(t, testStressSurpriseServerCloses, []testMode{http1Mode})
   840  }
   841  func testStressSurpriseServerCloses(t *testing.T, mode testMode) {
   842  	if testing.Short() {
   843  		t.Skip("skipping test in short mode")
   844  	}
   845  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   846  		w.Header().Set("Content-Length", "5")
   847  		w.Header().Set("Content-Type", "text/plain")
   848  		w.Write([]byte("Hello"))
   849  		w.(Flusher).Flush()
   850  		conn, buf, _ := w.(Hijacker).Hijack()
   851  		buf.Flush()
   852  		conn.Close()
   853  	})).ts
   854  	c := ts.Client()
   855  
   856  	// Do a bunch of traffic from different goroutines. Send to activityc
   857  	// after each request completes, regardless of whether it failed.
   858  	// If these are too high, OS X exhausts its ephemeral ports
   859  	// and hangs waiting for them to transition TCP states. That's
   860  	// not what we want to test. TODO(bradfitz): use an io.Pipe
   861  	// dialer for this test instead?
   862  	const (
   863  		numClients    = 20
   864  		reqsPerClient = 25
   865  	)
   866  	activityc := make(chan bool)
   867  	for i := 0; i < numClients; i++ {
   868  		go func() {
   869  			for i := 0; i < reqsPerClient; i++ {
   870  				res, err := c.Get(ts.URL)
   871  				if err == nil {
   872  					// We expect errors since the server is
   873  					// hanging up on us after telling us to
   874  					// send more requests, so we don't
   875  					// actually care what the error is.
   876  					// But we want to close the body in cases
   877  					// where we won the race.
   878  					res.Body.Close()
   879  				}
   880  				if !<-activityc { // Receives false when close(activityc) is executed
   881  					return
   882  				}
   883  			}
   884  		}()
   885  	}
   886  
   887  	// Make sure all the request come back, one way or another.
   888  	for i := 0; i < numClients*reqsPerClient; i++ {
   889  		select {
   890  		case activityc <- true:
   891  		case <-time.After(5 * time.Second):
   892  			close(activityc)
   893  			t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
   894  		}
   895  	}
   896  }
   897  
   898  // TestTransportHeadResponses verifies that we deal with Content-Lengths
   899  // with no bodies properly
   900  func TestTransportHeadResponses(t *testing.T) { run(t, testTransportHeadResponses) }
   901  func testTransportHeadResponses(t *testing.T, mode testMode) {
   902  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   903  		if r.Method != "HEAD" {
   904  			panic("expected HEAD; got " + r.Method)
   905  		}
   906  		w.Header().Set("Content-Length", "123")
   907  		w.WriteHeader(200)
   908  	})).ts
   909  	c := ts.Client()
   910  
   911  	for i := 0; i < 2; i++ {
   912  		res, err := c.Head(ts.URL)
   913  		if err != nil {
   914  			t.Errorf("error on loop %d: %v", i, err)
   915  			continue
   916  		}
   917  		if e, g := "123", res.Header.Get("Content-Length"); e != g {
   918  			t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
   919  		}
   920  		if e, g := int64(123), res.ContentLength; e != g {
   921  			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
   922  		}
   923  		if all, err := io.ReadAll(res.Body); err != nil {
   924  			t.Errorf("loop %d: Body ReadAll: %v", i, err)
   925  		} else if len(all) != 0 {
   926  			t.Errorf("Bogus body %q", all)
   927  		}
   928  	}
   929  }
   930  
   931  // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
   932  // on responses to HEAD requests.
   933  func TestTransportHeadChunkedResponse(t *testing.T) {
   934  	run(t, testTransportHeadChunkedResponse, []testMode{http1Mode}, testNotParallel)
   935  }
   936  func testTransportHeadChunkedResponse(t *testing.T, mode testMode) {
   937  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
   938  		if r.Method != "HEAD" {
   939  			panic("expected HEAD; got " + r.Method)
   940  		}
   941  		w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
   942  		w.Header().Set("x-client-ipport", r.RemoteAddr)
   943  		w.WriteHeader(200)
   944  	})).ts
   945  	c := ts.Client()
   946  
   947  	// Ensure that we wait for the readLoop to complete before
   948  	// calling Head again
   949  	didRead := make(chan bool)
   950  	SetReadLoopBeforeNextReadHook(func() { didRead <- true })
   951  	defer SetReadLoopBeforeNextReadHook(nil)
   952  
   953  	res1, err := c.Head(ts.URL)
   954  	<-didRead
   955  
   956  	if err != nil {
   957  		t.Fatalf("request 1 error: %v", err)
   958  	}
   959  
   960  	res2, err := c.Head(ts.URL)
   961  	<-didRead
   962  
   963  	if err != nil {
   964  		t.Fatalf("request 2 error: %v", err)
   965  	}
   966  	if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
   967  		t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
   968  	}
   969  }
   970  
   971  var roundTripTests = []struct {
   972  	accept       string
   973  	expectAccept string
   974  	compressed   bool
   975  }{
   976  	// Requests with no accept-encoding header use transparent compression
   977  	{"", "gzip", false},
   978  	// Requests with other accept-encoding should pass through unmodified
   979  	{"foo", "foo", false},
   980  	// Requests with accept-encoding == gzip should be passed through
   981  	{"gzip", "gzip", true},
   982  }
   983  
   984  // Test that the modification made to the Request by the RoundTripper is cleaned up
   985  func TestRoundTripGzip(t *testing.T) { run(t, testRoundTripGzip) }
   986  func testRoundTripGzip(t *testing.T, mode testMode) {
   987  	const responseBody = "test response body"
   988  	ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
   989  		accept := req.Header.Get("Accept-Encoding")
   990  		if expect := req.FormValue("expect_accept"); accept != expect {
   991  			t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q",
   992  				req.FormValue("testnum"), accept, expect)
   993  		}
   994  		if accept == "gzip" {
   995  			rw.Header().Set("Content-Encoding", "gzip")
   996  			gz := gzip.NewWriter(rw)
   997  			gz.Write([]byte(responseBody))
   998  			gz.Close()
   999  		} else {
  1000  			rw.Header().Set("Content-Encoding", accept)
  1001  			rw.Write([]byte(responseBody))
  1002  		}
  1003  	})).ts
  1004  	tr := ts.Client().Transport.(*Transport)
  1005  
  1006  	for i, test := range roundTripTests {
  1007  		// Test basic request (no accept-encoding)
  1008  		req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil)
  1009  		if test.accept != "" {
  1010  			req.Header.Set("Accept-Encoding", test.accept)
  1011  		}
  1012  		res, err := tr.RoundTrip(req)
  1013  		if err != nil {
  1014  			t.Errorf("%d. RoundTrip: %v", i, err)
  1015  			continue
  1016  		}
  1017  		var body []byte
  1018  		if test.compressed {
  1019  			var r *gzip.Reader
  1020  			r, err = gzip.NewReader(res.Body)
  1021  			if err != nil {
  1022  				t.Errorf("%d. gzip NewReader: %v", i, err)
  1023  				continue
  1024  			}
  1025  			body, err = io.ReadAll(r)
  1026  			res.Body.Close()
  1027  		} else {
  1028  			body, err = io.ReadAll(res.Body)
  1029  		}
  1030  		if err != nil {
  1031  			t.Errorf("%d. Error: %q", i, err)
  1032  			continue
  1033  		}
  1034  		if g, e := string(body), responseBody; g != e {
  1035  			t.Errorf("%d. body = %q; want %q", i, g, e)
  1036  		}
  1037  		if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
  1038  			t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e)
  1039  		}
  1040  		if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
  1041  			t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
  1042  		}
  1043  	}
  1044  
  1045  }
  1046  
  1047  func TestTransportGzip(t *testing.T) { run(t, testTransportGzip) }
  1048  func testTransportGzip(t *testing.T, mode testMode) {
  1049  	if mode == http2Mode {
  1050  		t.Skip("https://go.dev/issue/56020")
  1051  	}
  1052  	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  1053  	const nRandBytes = 1024 * 1024
  1054  	ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
  1055  		if req.Method == "HEAD" {
  1056  			if g := req.Header.Get("Accept-Encoding"); g != "" {
  1057  				t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g)
  1058  			}
  1059  			return
  1060  		}
  1061  		if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
  1062  			t.Errorf("Accept-Encoding = %q, want %q", g, e)
  1063  		}
  1064  		rw.Header().Set("Content-Encoding", "gzip")
  1065  
  1066  		var w io.Writer = rw
  1067  		var buf bytes.Buffer
  1068  		if req.FormValue("chunked") == "0" {
  1069  			w = &buf
  1070  			defer io.Copy(rw, &buf)
  1071  			defer func() {
  1072  				rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
  1073  			}()
  1074  		}
  1075  		gz := gzip.NewWriter(w)
  1076  		gz.Write([]byte(testString))
  1077  		if req.FormValue("body") == "large" {
  1078  			io.CopyN(gz, rand.Reader, nRandBytes)
  1079  		}
  1080  		gz.Close()
  1081  	})).ts
  1082  	c := ts.Client()
  1083  
  1084  	for _, chunked := range []string{"1", "0"} {
  1085  		// First fetch something large, but only read some of it.
  1086  		res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked)
  1087  		if err != nil {
  1088  			t.Fatalf("large get: %v", err)
  1089  		}
  1090  		buf := make([]byte, len(testString))
  1091  		n, err := io.ReadFull(res.Body, buf)
  1092  		if err != nil {
  1093  			t.Fatalf("partial read of large response: size=%d, %v", n, err)
  1094  		}
  1095  		if e, g := testString, string(buf); e != g {
  1096  			t.Errorf("partial read got %q, expected %q", g, e)
  1097  		}
  1098  		res.Body.Close()
  1099  		// Read on the body, even though it's closed
  1100  		n, err = res.Body.Read(buf)
  1101  		if n != 0 || err == nil {
  1102  			t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
  1103  		}
  1104  
  1105  		// Then something small.
  1106  		res, err = c.Get(ts.URL + "/?chunked=" + chunked)
  1107  		if err != nil {
  1108  			t.Fatal(err)
  1109  		}
  1110  		body, err := io.ReadAll(res.Body)
  1111  		if err != nil {
  1112  			t.Fatal(err)
  1113  		}
  1114  		if g, e := string(body), testString; g != e {
  1115  			t.Fatalf("body = %q; want %q", g, e)
  1116  		}
  1117  		if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
  1118  			t.Fatalf("Content-Encoding = %q; want %q", g, e)
  1119  		}
  1120  
  1121  		// Read on the body after it's been fully read:
  1122  		n, err = res.Body.Read(buf)
  1123  		if n != 0 || err == nil {
  1124  			t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
  1125  		}
  1126  		res.Body.Close()
  1127  		n, err = res.Body.Read(buf)
  1128  		if n != 0 || err == nil {
  1129  			t.Errorf("expected Read error after Close; got %d, %v", n, err)
  1130  		}
  1131  	}
  1132  
  1133  	// And a HEAD request too, because they're always weird.
  1134  	res, err := c.Head(ts.URL)
  1135  	if err != nil {
  1136  		t.Fatalf("Head: %v", err)
  1137  	}
  1138  	if res.StatusCode != 200 {
  1139  		t.Errorf("Head status=%d; want=200", res.StatusCode)
  1140  	}
  1141  }
  1142  
  1143  // If a request has Expect:100-continue header, the request blocks sending body until the first response.
  1144  // Premature consumption of the request body should not be occurred.
  1145  func TestTransportExpect100Continue(t *testing.T) {
  1146  	run(t, testTransportExpect100Continue, []testMode{http1Mode})
  1147  }
  1148  func testTransportExpect100Continue(t *testing.T, mode testMode) {
  1149  	ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
  1150  		switch req.URL.Path {
  1151  		case "/100":
  1152  			// This endpoint implicitly responds 100 Continue and reads body.
  1153  			if _, err := io.Copy(io.Discard, req.Body); err != nil {
  1154  				t.Error("Failed to read Body", err)
  1155  			}
  1156  			rw.WriteHeader(StatusOK)
  1157  		case "/200":
  1158  			// Go 1.5 adds Connection: close header if the client expect
  1159  			// continue but not entire request body is consumed.
  1160  			rw.WriteHeader(StatusOK)
  1161  		case "/500":
  1162  			rw.WriteHeader(StatusInternalServerError)
  1163  		case "/keepalive":
  1164  			// This hijacked endpoint responds error without Connection:close.
  1165  			_, bufrw, err := rw.(Hijacker).Hijack()
  1166  			if err != nil {
  1167  				log.Fatal(err)
  1168  			}
  1169  			bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n")
  1170  			bufrw.WriteString("Content-Length: 0\r\n\r\n")
  1171  			bufrw.Flush()
  1172  		case "/timeout":
  1173  			// This endpoint tries to read body without 100 (Continue) response.
  1174  			// After ExpectContinueTimeout, the reading will be started.
  1175  			conn, bufrw, err := rw.(Hijacker).Hijack()
  1176  			if err != nil {
  1177  				log.Fatal(err)
  1178  			}
  1179  			if _, err := io.CopyN(io.Discard, bufrw, req.ContentLength); err != nil {
  1180  				t.Error("Failed to read Body", err)
  1181  			}
  1182  			bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
  1183  			bufrw.Flush()
  1184  			conn.Close()
  1185  		}
  1186  
  1187  	})).ts
  1188  
  1189  	tests := []struct {
  1190  		path   string
  1191  		body   []byte
  1192  		sent   int
  1193  		status int
  1194  	}{
  1195  		{path: "/100", body: []byte("hello"), sent: 5, status: 200},       // Got 100 followed by 200, entire body is sent.
  1196  		{path: "/200", body: []byte("hello"), sent: 0, status: 200},       // Got 200 without 100. body isn't sent.
  1197  		{path: "/500", body: []byte("hello"), sent: 0, status: 500},       // Got 500 without 100. body isn't sent.
  1198  		{path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Although without Connection:close, body isn't sent.
  1199  		{path: "/timeout", body: []byte("hello"), sent: 5, status: 200},   // Timeout exceeded and entire body is sent.
  1200  	}
  1201  
  1202  	c := ts.Client()
  1203  	for i, v := range tests {
  1204  		tr := &Transport{
  1205  			ExpectContinueTimeout: 2 * time.Second,
  1206  		}
  1207  		defer tr.CloseIdleConnections()
  1208  		c.Transport = tr
  1209  		body := bytes.NewReader(v.body)
  1210  		req, err := NewRequest("PUT", ts.URL+v.path, body)
  1211  		if err != nil {
  1212  			t.Fatal(err)
  1213  		}
  1214  		req.Header.Set("Expect", "100-continue")
  1215  		req.ContentLength = int64(len(v.body))
  1216  
  1217  		resp, err := c.Do(req)
  1218  		if err != nil {
  1219  			t.Fatal(err)
  1220  		}
  1221  		resp.Body.Close()
  1222  
  1223  		sent := len(v.body) - body.Len()
  1224  		if v.status != resp.StatusCode {
  1225  			t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path)
  1226  		}
  1227  		if v.sent != sent {
  1228  			t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path)
  1229  		}
  1230  	}
  1231  }
  1232  
  1233  func TestSOCKS5Proxy(t *testing.T) {
  1234  	run(t, testSOCKS5Proxy, []testMode{http1Mode, https1Mode, http2Mode})
  1235  }
  1236  func testSOCKS5Proxy(t *testing.T, mode testMode) {
  1237  	ch := make(chan string, 1)
  1238  	l := newLocalListener(t)
  1239  	defer l.Close()
  1240  	defer close(ch)
  1241  	proxy := func(t *testing.T) {
  1242  		s, err := l.Accept()
  1243  		if err != nil {
  1244  			t.Errorf("socks5 proxy Accept(): %v", err)
  1245  			return
  1246  		}
  1247  		defer s.Close()
  1248  		var buf [22]byte
  1249  		if _, err := io.ReadFull(s, buf[:3]); err != nil {
  1250  			t.Errorf("socks5 proxy initial read: %v", err)
  1251  			return
  1252  		}
  1253  		if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) {
  1254  			t.Errorf("socks5 proxy initial read: got %v, want %v", buf[:3], want)
  1255  			return
  1256  		}
  1257  		if _, err := s.Write([]byte{5, 0}); err != nil {
  1258  			t.Errorf("socks5 proxy initial write: %v", err)
  1259  			return
  1260  		}
  1261  		if _, err := io.ReadFull(s, buf[:4]); err != nil {
  1262  			t.Errorf("socks5 proxy second read: %v", err)
  1263  			return
  1264  		}
  1265  		if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) {
  1266  			t.Errorf("socks5 proxy second read: got %v, want %v", buf[:3], want)
  1267  			return
  1268  		}
  1269  		var ipLen int
  1270  		switch buf[3] {
  1271  		case 1:
  1272  			ipLen = net.IPv4len
  1273  		case 4:
  1274  			ipLen = net.IPv6len
  1275  		default:
  1276  			t.Errorf("socks5 proxy second read: unexpected address type %v", buf[4])
  1277  			return
  1278  		}
  1279  		if _, err := io.ReadFull(s, buf[4:ipLen+6]); err != nil {
  1280  			t.Errorf("socks5 proxy address read: %v", err)
  1281  			return
  1282  		}
  1283  		ip := net.IP(buf[4 : ipLen+4])
  1284  		port := binary.BigEndian.Uint16(buf[ipLen+4 : ipLen+6])
  1285  		copy(buf[:3], []byte{5, 0, 0})
  1286  		if _, err := s.Write(buf[:ipLen+6]); err != nil {
  1287  			t.Errorf("socks5 proxy connect write: %v", err)
  1288  			return
  1289  		}
  1290  		ch <- fmt.Sprintf("proxy for %s:%d", ip, port)
  1291  
  1292  		// Implement proxying.
  1293  		targetHost := net.JoinHostPort(ip.String(), strconv.Itoa(int(port)))
  1294  		targetConn, err := net.Dial("tcp", targetHost)
  1295  		if err != nil {
  1296  			t.Errorf("net.Dial failed")
  1297  			return
  1298  		}
  1299  		go io.Copy(targetConn, s)
  1300  		io.Copy(s, targetConn) // Wait for the client to close the socket.
  1301  		targetConn.Close()
  1302  	}
  1303  
  1304  	pu, err := url.Parse("socks5://" + l.Addr().String())
  1305  	if err != nil {
  1306  		t.Fatal(err)
  1307  	}
  1308  
  1309  	sentinelHeader := "X-Sentinel"
  1310  	sentinelValue := "12345"
  1311  	h := HandlerFunc(func(w ResponseWriter, r *Request) {
  1312  		w.Header().Set(sentinelHeader, sentinelValue)
  1313  	})
  1314  	for _, useTLS := range []bool{false, true} {
  1315  		t.Run(fmt.Sprintf("useTLS=%v", useTLS), func(t *testing.T) {
  1316  			ts := newClientServerTest(t, mode, h).ts
  1317  			go proxy(t)
  1318  			c := ts.Client()
  1319  			c.Transport.(*Transport).Proxy = ProxyURL(pu)
  1320  			r, err := c.Head(ts.URL)
  1321  			if err != nil {
  1322  				t.Fatal(err)
  1323  			}
  1324  			if r.Header.Get(sentinelHeader) != sentinelValue {
  1325  				t.Errorf("Failed to retrieve sentinel value")
  1326  			}
  1327  			var got string
  1328  			select {
  1329  			case got = <-ch:
  1330  			case <-time.After(5 * time.Second):
  1331  				t.Fatal("timeout connecting to socks5 proxy")
  1332  			}
  1333  			ts.Close()
  1334  			tsu, err := url.Parse(ts.URL)
  1335  			if err != nil {
  1336  				t.Fatal(err)
  1337  			}
  1338  			want := "proxy for " + tsu.Host
  1339  			if got != want {
  1340  				t.Errorf("got %q, want %q", got, want)
  1341  			}
  1342  		})
  1343  	}
  1344  }
  1345  
  1346  func TestTransportProxy(t *testing.T) {
  1347  	defer afterTest(t)
  1348  	testCases := []struct{ siteMode, proxyMode testMode }{
  1349  		{http1Mode, http1Mode},
  1350  		{http1Mode, https1Mode},
  1351  		{https1Mode, http1Mode},
  1352  		{https1Mode, https1Mode},
  1353  	}
  1354  	for _, testCase := range testCases {
  1355  		siteMode := testCase.siteMode
  1356  		proxyMode := testCase.proxyMode
  1357  		t.Run(fmt.Sprintf("site=%v/proxy=%v", siteMode, proxyMode), func(t *testing.T) {
  1358  			siteCh := make(chan *Request, 1)
  1359  			h1 := HandlerFunc(func(w ResponseWriter, r *Request) {
  1360  				siteCh <- r
  1361  			})
  1362  			proxyCh := make(chan *Request, 1)
  1363  			h2 := HandlerFunc(func(w ResponseWriter, r *Request) {
  1364  				proxyCh <- r
  1365  				// Implement an entire CONNECT proxy
  1366  				if r.Method == "CONNECT" {
  1367  					hijacker, ok := w.(Hijacker)
  1368  					if !ok {
  1369  						t.Errorf("hijack not allowed")
  1370  						return
  1371  					}
  1372  					clientConn, _, err := hijacker.Hijack()
  1373  					if err != nil {
  1374  						t.Errorf("hijacking failed")
  1375  						return
  1376  					}
  1377  					res := &Response{
  1378  						StatusCode: StatusOK,
  1379  						Proto:      "HTTP/1.1",
  1380  						ProtoMajor: 1,
  1381  						ProtoMinor: 1,
  1382  						Header:     make(Header),
  1383  					}
  1384  
  1385  					targetConn, err := net.Dial("tcp", r.URL.Host)
  1386  					if err != nil {
  1387  						t.Errorf("net.Dial(%q) failed: %v", r.URL.Host, err)
  1388  						return
  1389  					}
  1390  
  1391  					if err := res.Write(clientConn); err != nil {
  1392  						t.Errorf("Writing 200 OK failed: %v", err)
  1393  						return
  1394  					}
  1395  
  1396  					go io.Copy(targetConn, clientConn)
  1397  					go func() {
  1398  						io.Copy(clientConn, targetConn)
  1399  						targetConn.Close()
  1400  					}()
  1401  				}
  1402  			})
  1403  			ts := newClientServerTest(t, siteMode, h1).ts
  1404  			proxy := newClientServerTest(t, proxyMode, h2).ts
  1405  
  1406  			pu, err := url.Parse(proxy.URL)
  1407  			if err != nil {
  1408  				t.Fatal(err)
  1409  			}
  1410  
  1411  			// If neither server is HTTPS or both are, then c may be derived from either.
  1412  			// If only one server is HTTPS, c must be derived from that server in order
  1413  			// to ensure that it is configured to use the fake root CA from testcert.go.
  1414  			c := proxy.Client()
  1415  			if siteMode == https1Mode {
  1416  				c = ts.Client()
  1417  			}
  1418  
  1419  			c.Transport.(*Transport).Proxy = ProxyURL(pu)
  1420  			if _, err := c.Head(ts.URL); err != nil {
  1421  				t.Error(err)
  1422  			}
  1423  			var got *Request
  1424  			select {
  1425  			case got = <-proxyCh:
  1426  			case <-time.After(5 * time.Second):
  1427  				t.Fatal("timeout connecting to http proxy")
  1428  			}
  1429  			c.Transport.(*Transport).CloseIdleConnections()
  1430  			ts.Close()
  1431  			proxy.Close()
  1432  			if siteMode == https1Mode {
  1433  				// First message should be a CONNECT, asking for a socket to the real server,
  1434  				if got.Method != "CONNECT" {
  1435  					t.Errorf("Wrong method for secure proxying: %q", got.Method)
  1436  				}
  1437  				gotHost := got.URL.Host
  1438  				pu, err := url.Parse(ts.URL)
  1439  				if err != nil {
  1440  					t.Fatal("Invalid site URL")
  1441  				}
  1442  				if wantHost := pu.Host; gotHost != wantHost {
  1443  					t.Errorf("Got CONNECT host %q, want %q", gotHost, wantHost)
  1444  				}
  1445  
  1446  				// The next message on the channel should be from the site's server.
  1447  				next := <-siteCh
  1448  				if next.Method != "HEAD" {
  1449  					t.Errorf("Wrong method at destination: %s", next.Method)
  1450  				}
  1451  				if nextURL := next.URL.String(); nextURL != "/" {
  1452  					t.Errorf("Wrong URL at destination: %s", nextURL)
  1453  				}
  1454  			} else {
  1455  				if got.Method != "HEAD" {
  1456  					t.Errorf("Wrong method for destination: %q", got.Method)
  1457  				}
  1458  				gotURL := got.URL.String()
  1459  				wantURL := ts.URL + "/"
  1460  				if gotURL != wantURL {
  1461  					t.Errorf("Got URL %q, want %q", gotURL, wantURL)
  1462  				}
  1463  			}
  1464  		})
  1465  	}
  1466  }
  1467  
  1468  // Issue 28012: verify that the Transport closes its TCP connection to http proxies
  1469  // when they're slow to reply to HTTPS CONNECT responses.
  1470  func TestTransportProxyHTTPSConnectLeak(t *testing.T) {
  1471  	setParallel(t)
  1472  	defer afterTest(t)
  1473  
  1474  	ctx, cancel := context.WithCancel(context.Background())
  1475  	defer cancel()
  1476  
  1477  	ln := newLocalListener(t)
  1478  	defer ln.Close()
  1479  	listenerDone := make(chan struct{})
  1480  	go func() {
  1481  		defer close(listenerDone)
  1482  		c, err := ln.Accept()
  1483  		if err != nil {
  1484  			t.Errorf("Accept: %v", err)
  1485  			return
  1486  		}
  1487  		defer c.Close()
  1488  		// Read the CONNECT request
  1489  		br := bufio.NewReader(c)
  1490  		cr, err := ReadRequest(br)
  1491  		if err != nil {
  1492  			t.Errorf("proxy server failed to read CONNECT request")
  1493  			return
  1494  		}
  1495  		if cr.Method != "CONNECT" {
  1496  			t.Errorf("unexpected method %q", cr.Method)
  1497  			return
  1498  		}
  1499  
  1500  		// Now hang and never write a response; instead, cancel the request and wait
  1501  		// for the client to close.
  1502  		// (Prior to Issue 28012 being fixed, we never closed.)
  1503  		cancel()
  1504  		var buf [1]byte
  1505  		_, err = br.Read(buf[:])
  1506  		if err != io.EOF {
  1507  			t.Errorf("proxy server Read err = %v; want EOF", err)
  1508  		}
  1509  		return
  1510  	}()
  1511  
  1512  	c := &Client{
  1513  		Transport: &Transport{
  1514  			Proxy: func(*Request) (*url.URL, error) {
  1515  				return url.Parse("http://" + ln.Addr().String())
  1516  			},
  1517  		},
  1518  	}
  1519  	req, err := NewRequestWithContext(ctx, "GET", "https://golang.fake.tld/", nil)
  1520  	if err != nil {
  1521  		t.Fatal(err)
  1522  	}
  1523  	_, err = c.Do(req)
  1524  	if err == nil {
  1525  		t.Errorf("unexpected Get success")
  1526  	}
  1527  
  1528  	// Wait unconditionally for the listener goroutine to exit: this should never
  1529  	// hang, so if it does we want a full goroutine dump — and that's exactly what
  1530  	// the testing package will give us when the test run times out.
  1531  	<-listenerDone
  1532  }
  1533  
  1534  // Issue 16997: test transport dial preserves typed errors
  1535  func TestTransportDialPreservesNetOpProxyError(t *testing.T) {
  1536  	defer afterTest(t)
  1537  
  1538  	var errDial = errors.New("some dial error")
  1539  
  1540  	tr := &Transport{
  1541  		Proxy: func(*Request) (*url.URL, error) {
  1542  			return url.Parse("http://proxy.fake.tld/")
  1543  		},
  1544  		Dial: func(string, string) (net.Conn, error) {
  1545  			return nil, errDial
  1546  		},
  1547  	}
  1548  	defer tr.CloseIdleConnections()
  1549  
  1550  	c := &Client{Transport: tr}
  1551  	req, _ := NewRequest("GET", "http://fake.tld", nil)
  1552  	res, err := c.Do(req)
  1553  	if err == nil {
  1554  		res.Body.Close()
  1555  		t.Fatal("wanted a non-nil error")
  1556  	}
  1557  
  1558  	uerr, ok := err.(*url.Error)
  1559  	if !ok {
  1560  		t.Fatalf("got %T, want *url.Error", err)
  1561  	}
  1562  	oe, ok := uerr.Err.(*net.OpError)
  1563  	if !ok {
  1564  		t.Fatalf("url.Error.Err =  %T; want *net.OpError", uerr.Err)
  1565  	}
  1566  	want := &net.OpError{
  1567  		Op:  "proxyconnect",
  1568  		Net: "tcp",
  1569  		Err: errDial, // original error, unwrapped.
  1570  	}
  1571  	if !reflect.DeepEqual(oe, want) {
  1572  		t.Errorf("Got error %#v; want %#v", oe, want)
  1573  	}
  1574  }
  1575  
  1576  // Issue 36431: calls to RoundTrip should not mutate t.ProxyConnectHeader.
  1577  //
  1578  // (A bug caused dialConn to instead write the per-request Proxy-Authorization
  1579  // header through to the shared Header instance, introducing a data race.)
  1580  func TestTransportProxyDialDoesNotMutateProxyConnectHeader(t *testing.T) {
  1581  	run(t, testTransportProxyDialDoesNotMutateProxyConnectHeader)
  1582  }
  1583  func testTransportProxyDialDoesNotMutateProxyConnectHeader(t *testing.T, mode testMode) {
  1584  	proxy := newClientServerTest(t, mode, NotFoundHandler()).ts
  1585  	defer proxy.Close()
  1586  	c := proxy.Client()
  1587  
  1588  	tr := c.Transport.(*Transport)
  1589  	tr.Proxy = func(*Request) (*url.URL, error) {
  1590  		u, _ := url.Parse(proxy.URL)
  1591  		u.User = url.UserPassword("aladdin", "opensesame")
  1592  		return u, nil
  1593  	}
  1594  	h := tr.ProxyConnectHeader
  1595  	if h == nil {
  1596  		h = make(Header)
  1597  	}
  1598  	tr.ProxyConnectHeader = h.Clone()
  1599  
  1600  	req, err := NewRequest("GET", "https://golang.fake.tld/", nil)
  1601  	if err != nil {
  1602  		t.Fatal(err)
  1603  	}
  1604  	_, err = c.Do(req)
  1605  	if err == nil {
  1606  		t.Errorf("unexpected Get success")
  1607  	}
  1608  
  1609  	if !reflect.DeepEqual(tr.ProxyConnectHeader, h) {
  1610  		t.Errorf("tr.ProxyConnectHeader = %v; want %v", tr.ProxyConnectHeader, h)
  1611  	}
  1612  }
  1613  
  1614  // TestTransportGzipRecursive sends a gzip quine and checks that the
  1615  // client gets the same value back. This is more cute than anything,
  1616  // but checks that we don't recurse forever, and checks that
  1617  // Content-Encoding is removed.
  1618  func TestTransportGzipRecursive(t *testing.T) { run(t, testTransportGzipRecursive) }
  1619  func testTransportGzipRecursive(t *testing.T, mode testMode) {
  1620  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1621  		w.Header().Set("Content-Encoding", "gzip")
  1622  		w.Write(rgz)
  1623  	})).ts
  1624  
  1625  	c := ts.Client()
  1626  	res, err := c.Get(ts.URL)
  1627  	if err != nil {
  1628  		t.Fatal(err)
  1629  	}
  1630  	body, err := io.ReadAll(res.Body)
  1631  	if err != nil {
  1632  		t.Fatal(err)
  1633  	}
  1634  	if !bytes.Equal(body, rgz) {
  1635  		t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x",
  1636  			body, rgz)
  1637  	}
  1638  	if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
  1639  		t.Fatalf("Content-Encoding = %q; want %q", g, e)
  1640  	}
  1641  }
  1642  
  1643  // golang.org/issue/7750: request fails when server replies with
  1644  // a short gzip body
  1645  func TestTransportGzipShort(t *testing.T) { run(t, testTransportGzipShort) }
  1646  func testTransportGzipShort(t *testing.T, mode testMode) {
  1647  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1648  		w.Header().Set("Content-Encoding", "gzip")
  1649  		w.Write([]byte{0x1f, 0x8b})
  1650  	})).ts
  1651  
  1652  	c := ts.Client()
  1653  	res, err := c.Get(ts.URL)
  1654  	if err != nil {
  1655  		t.Fatal(err)
  1656  	}
  1657  	defer res.Body.Close()
  1658  	_, err = io.ReadAll(res.Body)
  1659  	if err == nil {
  1660  		t.Fatal("Expect an error from reading a body.")
  1661  	}
  1662  	if err != io.ErrUnexpectedEOF {
  1663  		t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err)
  1664  	}
  1665  }
  1666  
  1667  // Wait until number of goroutines is no greater than nmax, or time out.
  1668  func waitNumGoroutine(nmax int) int {
  1669  	nfinal := runtime.NumGoroutine()
  1670  	for ntries := 10; ntries > 0 && nfinal > nmax; ntries-- {
  1671  		time.Sleep(50 * time.Millisecond)
  1672  		runtime.GC()
  1673  		nfinal = runtime.NumGoroutine()
  1674  	}
  1675  	return nfinal
  1676  }
  1677  
  1678  // tests that persistent goroutine connections shut down when no longer desired.
  1679  func TestTransportPersistConnLeak(t *testing.T) {
  1680  	run(t, testTransportPersistConnLeak, testNotParallel)
  1681  }
  1682  func testTransportPersistConnLeak(t *testing.T, mode testMode) {
  1683  	if mode == http2Mode {
  1684  		t.Skip("flaky in HTTP/2")
  1685  	}
  1686  	// Not parallel: counts goroutines
  1687  
  1688  	const numReq = 25
  1689  	gotReqCh := make(chan bool, numReq)
  1690  	unblockCh := make(chan bool, numReq)
  1691  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1692  		gotReqCh <- true
  1693  		<-unblockCh
  1694  		w.Header().Set("Content-Length", "0")
  1695  		w.WriteHeader(204)
  1696  	})).ts
  1697  	c := ts.Client()
  1698  	tr := c.Transport.(*Transport)
  1699  
  1700  	n0 := runtime.NumGoroutine()
  1701  
  1702  	didReqCh := make(chan bool, numReq)
  1703  	failed := make(chan bool, numReq)
  1704  	for i := 0; i < numReq; i++ {
  1705  		go func() {
  1706  			res, err := c.Get(ts.URL)
  1707  			didReqCh <- true
  1708  			if err != nil {
  1709  				t.Logf("client fetch error: %v", err)
  1710  				failed <- true
  1711  				return
  1712  			}
  1713  			res.Body.Close()
  1714  		}()
  1715  	}
  1716  
  1717  	// Wait for all goroutines to be stuck in the Handler.
  1718  	for i := 0; i < numReq; i++ {
  1719  		select {
  1720  		case <-gotReqCh:
  1721  			// ok
  1722  		case <-failed:
  1723  			// Not great but not what we are testing:
  1724  			// sometimes an overloaded system will fail to make all the connections.
  1725  		}
  1726  	}
  1727  
  1728  	nhigh := runtime.NumGoroutine()
  1729  
  1730  	// Tell all handlers to unblock and reply.
  1731  	close(unblockCh)
  1732  
  1733  	// Wait for all HTTP clients to be done.
  1734  	for i := 0; i < numReq; i++ {
  1735  		<-didReqCh
  1736  	}
  1737  
  1738  	tr.CloseIdleConnections()
  1739  	nfinal := waitNumGoroutine(n0 + 5)
  1740  
  1741  	growth := nfinal - n0
  1742  
  1743  	// We expect 0 or 1 extra goroutine, empirically. Allow up to 5.
  1744  	// Previously we were leaking one per numReq.
  1745  	if int(growth) > 5 {
  1746  		t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
  1747  		t.Error("too many new goroutines")
  1748  	}
  1749  }
  1750  
  1751  // golang.org/issue/4531: Transport leaks goroutines when
  1752  // request.ContentLength is explicitly short
  1753  func TestTransportPersistConnLeakShortBody(t *testing.T) {
  1754  	run(t, testTransportPersistConnLeakShortBody, testNotParallel)
  1755  }
  1756  func testTransportPersistConnLeakShortBody(t *testing.T, mode testMode) {
  1757  	if mode == http2Mode {
  1758  		t.Skip("flaky in HTTP/2")
  1759  	}
  1760  
  1761  	// Not parallel: measures goroutines.
  1762  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1763  	})).ts
  1764  	c := ts.Client()
  1765  	tr := c.Transport.(*Transport)
  1766  
  1767  	n0 := runtime.NumGoroutine()
  1768  	body := []byte("Hello")
  1769  	for i := 0; i < 20; i++ {
  1770  		req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
  1771  		if err != nil {
  1772  			t.Fatal(err)
  1773  		}
  1774  		req.ContentLength = int64(len(body) - 2) // explicitly short
  1775  		_, err = c.Do(req)
  1776  		if err == nil {
  1777  			t.Fatal("Expect an error from writing too long of a body.")
  1778  		}
  1779  	}
  1780  	nhigh := runtime.NumGoroutine()
  1781  	tr.CloseIdleConnections()
  1782  	nfinal := waitNumGoroutine(n0 + 5)
  1783  
  1784  	growth := nfinal - n0
  1785  
  1786  	// We expect 0 or 1 extra goroutine, empirically. Allow up to 5.
  1787  	// Previously we were leaking one per numReq.
  1788  	t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
  1789  	if int(growth) > 5 {
  1790  		t.Error("too many new goroutines")
  1791  	}
  1792  }
  1793  
  1794  // A countedConn is a net.Conn that decrements an atomic counter when finalized.
  1795  type countedConn struct {
  1796  	net.Conn
  1797  }
  1798  
  1799  // A countingDialer dials connections and counts the number that remain reachable.
  1800  type countingDialer struct {
  1801  	dialer      net.Dialer
  1802  	mu          sync.Mutex
  1803  	total, live int64
  1804  }
  1805  
  1806  func (d *countingDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
  1807  	conn, err := d.dialer.DialContext(ctx, network, address)
  1808  	if err != nil {
  1809  		return nil, err
  1810  	}
  1811  
  1812  	counted := new(countedConn)
  1813  	counted.Conn = conn
  1814  
  1815  	d.mu.Lock()
  1816  	defer d.mu.Unlock()
  1817  	d.total++
  1818  	d.live++
  1819  
  1820  	runtime.SetFinalizer(counted, d.decrement)
  1821  	return counted, nil
  1822  }
  1823  
  1824  func (d *countingDialer) decrement(*countedConn) {
  1825  	d.mu.Lock()
  1826  	defer d.mu.Unlock()
  1827  	d.live--
  1828  }
  1829  
  1830  func (d *countingDialer) Read() (total, live int64) {
  1831  	d.mu.Lock()
  1832  	defer d.mu.Unlock()
  1833  	return d.total, d.live
  1834  }
  1835  
  1836  func TestTransportPersistConnLeakNeverIdle(t *testing.T) {
  1837  	run(t, testTransportPersistConnLeakNeverIdle, []testMode{http1Mode})
  1838  }
  1839  func testTransportPersistConnLeakNeverIdle(t *testing.T, mode testMode) {
  1840  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1841  		// Close every connection so that it cannot be kept alive.
  1842  		conn, _, err := w.(Hijacker).Hijack()
  1843  		if err != nil {
  1844  			t.Errorf("Hijack failed unexpectedly: %v", err)
  1845  			return
  1846  		}
  1847  		conn.Close()
  1848  	})).ts
  1849  
  1850  	var d countingDialer
  1851  	c := ts.Client()
  1852  	c.Transport.(*Transport).DialContext = d.DialContext
  1853  
  1854  	body := []byte("Hello")
  1855  	for i := 0; ; i++ {
  1856  		total, live := d.Read()
  1857  		if live < total {
  1858  			break
  1859  		}
  1860  		if i >= 1<<12 {
  1861  			t.Fatalf("Count of live client net.Conns (%d) not lower than total (%d) after %d Do / GC iterations.", live, total, i)
  1862  		}
  1863  
  1864  		req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
  1865  		if err != nil {
  1866  			t.Fatal(err)
  1867  		}
  1868  		_, err = c.Do(req)
  1869  		if err == nil {
  1870  			t.Fatal("expected broken connection")
  1871  		}
  1872  
  1873  		runtime.GC()
  1874  	}
  1875  }
  1876  
  1877  type countedContext struct {
  1878  	context.Context
  1879  }
  1880  
  1881  type contextCounter struct {
  1882  	mu   sync.Mutex
  1883  	live int64
  1884  }
  1885  
  1886  func (cc *contextCounter) Track(ctx context.Context) context.Context {
  1887  	counted := new(countedContext)
  1888  	counted.Context = ctx
  1889  	cc.mu.Lock()
  1890  	defer cc.mu.Unlock()
  1891  	cc.live++
  1892  	runtime.SetFinalizer(counted, cc.decrement)
  1893  	return counted
  1894  }
  1895  
  1896  func (cc *contextCounter) decrement(*countedContext) {
  1897  	cc.mu.Lock()
  1898  	defer cc.mu.Unlock()
  1899  	cc.live--
  1900  }
  1901  
  1902  func (cc *contextCounter) Read() (live int64) {
  1903  	cc.mu.Lock()
  1904  	defer cc.mu.Unlock()
  1905  	return cc.live
  1906  }
  1907  
  1908  func TestTransportPersistConnContextLeakMaxConnsPerHost(t *testing.T) {
  1909  	run(t, testTransportPersistConnContextLeakMaxConnsPerHost)
  1910  }
  1911  func testTransportPersistConnContextLeakMaxConnsPerHost(t *testing.T, mode testMode) {
  1912  	if mode == http2Mode {
  1913  		t.Skip("https://go.dev/issue/56021")
  1914  	}
  1915  
  1916  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1917  		runtime.Gosched()
  1918  		w.WriteHeader(StatusOK)
  1919  	})).ts
  1920  
  1921  	c := ts.Client()
  1922  	c.Transport.(*Transport).MaxConnsPerHost = 1
  1923  
  1924  	ctx := context.Background()
  1925  	body := []byte("Hello")
  1926  	doPosts := func(cc *contextCounter) {
  1927  		var wg sync.WaitGroup
  1928  		for n := 64; n > 0; n-- {
  1929  			wg.Add(1)
  1930  			go func() {
  1931  				defer wg.Done()
  1932  
  1933  				ctx := cc.Track(ctx)
  1934  				req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
  1935  				if err != nil {
  1936  					t.Error(err)
  1937  				}
  1938  
  1939  				_, err = c.Do(req.WithContext(ctx))
  1940  				if err != nil {
  1941  					t.Errorf("Do failed with error: %v", err)
  1942  				}
  1943  			}()
  1944  		}
  1945  		wg.Wait()
  1946  	}
  1947  
  1948  	var initialCC contextCounter
  1949  	doPosts(&initialCC)
  1950  
  1951  	// flushCC exists only to put pressure on the GC to finalize the initialCC
  1952  	// contexts: the flushCC allocations should eventually displace the initialCC
  1953  	// allocations.
  1954  	var flushCC contextCounter
  1955  	for i := 0; ; i++ {
  1956  		live := initialCC.Read()
  1957  		if live == 0 {
  1958  			break
  1959  		}
  1960  		if i >= 100 {
  1961  			t.Fatalf("%d Contexts still not finalized after %d GC cycles.", live, i)
  1962  		}
  1963  		doPosts(&flushCC)
  1964  		runtime.GC()
  1965  	}
  1966  }
  1967  
  1968  // This used to crash; https://golang.org/issue/3266
  1969  func TestTransportIdleConnCrash(t *testing.T) { run(t, testTransportIdleConnCrash) }
  1970  func testTransportIdleConnCrash(t *testing.T, mode testMode) {
  1971  	var tr *Transport
  1972  
  1973  	unblockCh := make(chan bool, 1)
  1974  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  1975  		<-unblockCh
  1976  		tr.CloseIdleConnections()
  1977  	})).ts
  1978  	c := ts.Client()
  1979  	tr = c.Transport.(*Transport)
  1980  
  1981  	didreq := make(chan bool)
  1982  	go func() {
  1983  		res, err := c.Get(ts.URL)
  1984  		if err != nil {
  1985  			t.Error(err)
  1986  		} else {
  1987  			res.Body.Close() // returns idle conn
  1988  		}
  1989  		didreq <- true
  1990  	}()
  1991  	unblockCh <- true
  1992  	<-didreq
  1993  }
  1994  
  1995  // Test that the transport doesn't close the TCP connection early,
  1996  // before the response body has been read. This was a regression
  1997  // which sadly lacked a triggering test. The large response body made
  1998  // the old race easier to trigger.
  1999  func TestIssue3644(t *testing.T) { run(t, testIssue3644) }
  2000  func testIssue3644(t *testing.T, mode testMode) {
  2001  	const numFoos = 5000
  2002  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2003  		w.Header().Set("Connection", "close")
  2004  		for i := 0; i < numFoos; i++ {
  2005  			w.Write([]byte("foo "))
  2006  		}
  2007  	})).ts
  2008  	c := ts.Client()
  2009  	res, err := c.Get(ts.URL)
  2010  	if err != nil {
  2011  		t.Fatal(err)
  2012  	}
  2013  	defer res.Body.Close()
  2014  	bs, err := io.ReadAll(res.Body)
  2015  	if err != nil {
  2016  		t.Fatal(err)
  2017  	}
  2018  	if len(bs) != numFoos*len("foo ") {
  2019  		t.Errorf("unexpected response length")
  2020  	}
  2021  }
  2022  
  2023  // Test that a client receives a server's reply, even if the server doesn't read
  2024  // the entire request body.
  2025  func TestIssue3595(t *testing.T) { run(t, testIssue3595) }
  2026  func testIssue3595(t *testing.T, mode testMode) {
  2027  	const deniedMsg = "sorry, denied."
  2028  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2029  		Error(w, deniedMsg, StatusUnauthorized)
  2030  	})).ts
  2031  	c := ts.Client()
  2032  	res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a'))
  2033  	if err != nil {
  2034  		t.Errorf("Post: %v", err)
  2035  		return
  2036  	}
  2037  	got, err := io.ReadAll(res.Body)
  2038  	if err != nil {
  2039  		t.Fatalf("Body ReadAll: %v", err)
  2040  	}
  2041  	if !strings.Contains(string(got), deniedMsg) {
  2042  		t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg)
  2043  	}
  2044  }
  2045  
  2046  // From https://golang.org/issue/4454 ,
  2047  // "client fails to handle requests with no body and chunked encoding"
  2048  func TestChunkedNoContent(t *testing.T) { run(t, testChunkedNoContent) }
  2049  func testChunkedNoContent(t *testing.T, mode testMode) {
  2050  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2051  		w.WriteHeader(StatusNoContent)
  2052  	})).ts
  2053  
  2054  	c := ts.Client()
  2055  	for _, closeBody := range []bool{true, false} {
  2056  		const n = 4
  2057  		for i := 1; i <= n; i++ {
  2058  			res, err := c.Get(ts.URL)
  2059  			if err != nil {
  2060  				t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err)
  2061  			} else {
  2062  				if closeBody {
  2063  					res.Body.Close()
  2064  				}
  2065  			}
  2066  		}
  2067  	}
  2068  }
  2069  
  2070  func TestTransportConcurrency(t *testing.T) {
  2071  	run(t, testTransportConcurrency, testNotParallel, []testMode{http1Mode})
  2072  }
  2073  func testTransportConcurrency(t *testing.T, mode testMode) {
  2074  	// Not parallel: uses global test hooks.
  2075  	maxProcs, numReqs := 16, 500
  2076  	if testing.Short() {
  2077  		maxProcs, numReqs = 4, 50
  2078  	}
  2079  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
  2080  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2081  		fmt.Fprintf(w, "%v", r.FormValue("echo"))
  2082  	})).ts
  2083  
  2084  	var wg sync.WaitGroup
  2085  	wg.Add(numReqs)
  2086  
  2087  	// Due to the Transport's "socket late binding" (see
  2088  	// idleConnCh in transport.go), the numReqs HTTP requests
  2089  	// below can finish with a dial still outstanding. To keep
  2090  	// the leak checker happy, keep track of pending dials and
  2091  	// wait for them to finish (and be closed or returned to the
  2092  	// idle pool) before we close idle connections.
  2093  	SetPendingDialHooks(func() { wg.Add(1) }, wg.Done)
  2094  	defer SetPendingDialHooks(nil, nil)
  2095  
  2096  	c := ts.Client()
  2097  	reqs := make(chan string)
  2098  	defer close(reqs)
  2099  
  2100  	for i := 0; i < maxProcs*2; i++ {
  2101  		go func() {
  2102  			for req := range reqs {
  2103  				res, err := c.Get(ts.URL + "/?echo=" + req)
  2104  				if err != nil {
  2105  					if runtime.GOOS == "netbsd" && strings.HasSuffix(err.Error(), ": connection reset by peer") {
  2106  						// https://go.dev/issue/52168: this test was observed to fail with
  2107  						// ECONNRESET errors in Dial on various netbsd builders.
  2108  						t.Logf("error on req %s: %v", req, err)
  2109  						t.Logf("(see https://go.dev/issue/52168)")
  2110  					} else {
  2111  						t.Errorf("error on req %s: %v", req, err)
  2112  					}
  2113  					wg.Done()
  2114  					continue
  2115  				}
  2116  				all, err := io.ReadAll(res.Body)
  2117  				if err != nil {
  2118  					t.Errorf("read error on req %s: %v", req, err)
  2119  				} else if string(all) != req {
  2120  					t.Errorf("body of req %s = %q; want %q", req, all, req)
  2121  				}
  2122  				res.Body.Close()
  2123  				wg.Done()
  2124  			}
  2125  		}()
  2126  	}
  2127  	for i := 0; i < numReqs; i++ {
  2128  		reqs <- fmt.Sprintf("request-%d", i)
  2129  	}
  2130  	wg.Wait()
  2131  }
  2132  
  2133  func TestIssue4191_InfiniteGetTimeout(t *testing.T) { run(t, testIssue4191_InfiniteGetTimeout) }
  2134  func testIssue4191_InfiniteGetTimeout(t *testing.T, mode testMode) {
  2135  	const debug = false
  2136  	mux := NewServeMux()
  2137  	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
  2138  		io.Copy(w, neverEnding('a'))
  2139  	})
  2140  	ts := newClientServerTest(t, mode, mux).ts
  2141  	timeout := 100 * time.Millisecond
  2142  
  2143  	c := ts.Client()
  2144  	c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) {
  2145  		conn, err := net.Dial(n, addr)
  2146  		if err != nil {
  2147  			return nil, err
  2148  		}
  2149  		conn.SetDeadline(time.Now().Add(timeout))
  2150  		if debug {
  2151  			conn = NewLoggingConn("client", conn)
  2152  		}
  2153  		return conn, nil
  2154  	}
  2155  
  2156  	getFailed := false
  2157  	nRuns := 5
  2158  	if testing.Short() {
  2159  		nRuns = 1
  2160  	}
  2161  	for i := 0; i < nRuns; i++ {
  2162  		if debug {
  2163  			println("run", i+1, "of", nRuns)
  2164  		}
  2165  		sres, err := c.Get(ts.URL + "/get")
  2166  		if err != nil {
  2167  			if !getFailed {
  2168  				// Make the timeout longer, once.
  2169  				getFailed = true
  2170  				t.Logf("increasing timeout")
  2171  				i--
  2172  				timeout *= 10
  2173  				continue
  2174  			}
  2175  			t.Errorf("Error issuing GET: %v", err)
  2176  			break
  2177  		}
  2178  		_, err = io.Copy(io.Discard, sres.Body)
  2179  		if err == nil {
  2180  			t.Errorf("Unexpected successful copy")
  2181  			break
  2182  		}
  2183  	}
  2184  	if debug {
  2185  		println("tests complete; waiting for handlers to finish")
  2186  	}
  2187  }
  2188  
  2189  func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
  2190  	run(t, testIssue4191_InfiniteGetToPutTimeout, []testMode{http1Mode})
  2191  }
  2192  func testIssue4191_InfiniteGetToPutTimeout(t *testing.T, mode testMode) {
  2193  	const debug = false
  2194  	mux := NewServeMux()
  2195  	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
  2196  		io.Copy(w, neverEnding('a'))
  2197  	})
  2198  	mux.HandleFunc("/put", func(w ResponseWriter, r *Request) {
  2199  		defer r.Body.Close()
  2200  		io.Copy(io.Discard, r.Body)
  2201  	})
  2202  	ts := newClientServerTest(t, mode, mux).ts
  2203  	timeout := 100 * time.Millisecond
  2204  
  2205  	c := ts.Client()
  2206  	c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) {
  2207  		conn, err := net.Dial(n, addr)
  2208  		if err != nil {
  2209  			return nil, err
  2210  		}
  2211  		conn.SetDeadline(time.Now().Add(timeout))
  2212  		if debug {
  2213  			conn = NewLoggingConn("client", conn)
  2214  		}
  2215  		return conn, nil
  2216  	}
  2217  
  2218  	getFailed := false
  2219  	nRuns := 5
  2220  	if testing.Short() {
  2221  		nRuns = 1
  2222  	}
  2223  	for i := 0; i < nRuns; i++ {
  2224  		if debug {
  2225  			println("run", i+1, "of", nRuns)
  2226  		}
  2227  		sres, err := c.Get(ts.URL + "/get")
  2228  		if err != nil {
  2229  			if !getFailed {
  2230  				// Make the timeout longer, once.
  2231  				getFailed = true
  2232  				t.Logf("increasing timeout")
  2233  				i--
  2234  				timeout *= 10
  2235  				continue
  2236  			}
  2237  			t.Errorf("Error issuing GET: %v", err)
  2238  			break
  2239  		}
  2240  		req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body)
  2241  		_, err = c.Do(req)
  2242  		if err == nil {
  2243  			sres.Body.Close()
  2244  			t.Errorf("Unexpected successful PUT")
  2245  			break
  2246  		}
  2247  		sres.Body.Close()
  2248  	}
  2249  	if debug {
  2250  		println("tests complete; waiting for handlers to finish")
  2251  	}
  2252  	ts.Close()
  2253  }
  2254  
  2255  func TestTransportResponseHeaderTimeout(t *testing.T) { run(t, testTransportResponseHeaderTimeout) }
  2256  func testTransportResponseHeaderTimeout(t *testing.T, mode testMode) {
  2257  	if testing.Short() {
  2258  		t.Skip("skipping timeout test in -short mode")
  2259  	}
  2260  	inHandler := make(chan bool, 1)
  2261  	mux := NewServeMux()
  2262  	mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) {
  2263  		inHandler <- true
  2264  	})
  2265  	mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) {
  2266  		inHandler <- true
  2267  		time.Sleep(2 * time.Second)
  2268  	})
  2269  	ts := newClientServerTest(t, mode, mux).ts
  2270  
  2271  	c := ts.Client()
  2272  	c.Transport.(*Transport).ResponseHeaderTimeout = 500 * time.Millisecond
  2273  
  2274  	tests := []struct {
  2275  		path    string
  2276  		want    int
  2277  		wantErr string
  2278  	}{
  2279  		{path: "/fast", want: 200},
  2280  		{path: "/slow", wantErr: "timeout awaiting response headers"},
  2281  		{path: "/fast", want: 200},
  2282  	}
  2283  	for i, tt := range tests {
  2284  		req, _ := NewRequest("GET", ts.URL+tt.path, nil)
  2285  		req = req.WithT(t)
  2286  		res, err := c.Do(req)
  2287  		select {
  2288  		case <-inHandler:
  2289  		case <-time.After(5 * time.Second):
  2290  			t.Errorf("never entered handler for test index %d, %s", i, tt.path)
  2291  			continue
  2292  		}
  2293  		if err != nil {
  2294  			uerr, ok := err.(*url.Error)
  2295  			if !ok {
  2296  				t.Errorf("error is not an url.Error; got: %#v", err)
  2297  				continue
  2298  			}
  2299  			nerr, ok := uerr.Err.(net.Error)
  2300  			if !ok {
  2301  				t.Errorf("error does not satisfy net.Error interface; got: %#v", err)
  2302  				continue
  2303  			}
  2304  			if !nerr.Timeout() {
  2305  				t.Errorf("want timeout error; got: %q", nerr)
  2306  				continue
  2307  			}
  2308  			if strings.Contains(err.Error(), tt.wantErr) {
  2309  				continue
  2310  			}
  2311  			t.Errorf("%d. unexpected error: %v", i, err)
  2312  			continue
  2313  		}
  2314  		if tt.wantErr != "" {
  2315  			t.Errorf("%d. no error. expected error: %v", i, tt.wantErr)
  2316  			continue
  2317  		}
  2318  		if res.StatusCode != tt.want {
  2319  			t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want)
  2320  		}
  2321  	}
  2322  }
  2323  
  2324  func TestTransportCancelRequest(t *testing.T) {
  2325  	run(t, testTransportCancelRequest, []testMode{http1Mode})
  2326  }
  2327  func testTransportCancelRequest(t *testing.T, mode testMode) {
  2328  	if testing.Short() {
  2329  		t.Skip("skipping test in -short mode")
  2330  	}
  2331  	unblockc := make(chan bool)
  2332  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2333  		fmt.Fprintf(w, "Hello")
  2334  		w.(Flusher).Flush() // send headers and some body
  2335  		<-unblockc
  2336  	})).ts
  2337  	defer close(unblockc)
  2338  
  2339  	c := ts.Client()
  2340  	tr := c.Transport.(*Transport)
  2341  
  2342  	req, _ := NewRequest("GET", ts.URL, nil)
  2343  	res, err := c.Do(req)
  2344  	if err != nil {
  2345  		t.Fatal(err)
  2346  	}
  2347  	go func() {
  2348  		time.Sleep(1 * time.Second)
  2349  		tr.CancelRequest(req)
  2350  	}()
  2351  	t0 := time.Now()
  2352  	body, err := io.ReadAll(res.Body)
  2353  	d := time.Since(t0)
  2354  
  2355  	if err != ExportErrRequestCanceled {
  2356  		t.Errorf("Body.Read error = %v; want errRequestCanceled", err)
  2357  	}
  2358  	if string(body) != "Hello" {
  2359  		t.Errorf("Body = %q; want Hello", body)
  2360  	}
  2361  	if d < 500*time.Millisecond {
  2362  		t.Errorf("expected ~1 second delay; got %v", d)
  2363  	}
  2364  	// Verify no outstanding requests after readLoop/writeLoop
  2365  	// goroutines shut down.
  2366  	for tries := 5; tries > 0; tries-- {
  2367  		n := tr.NumPendingRequestsForTesting()
  2368  		if n == 0 {
  2369  			break
  2370  		}
  2371  		time.Sleep(100 * time.Millisecond)
  2372  		if tries == 1 {
  2373  			t.Errorf("pending requests = %d; want 0", n)
  2374  		}
  2375  	}
  2376  }
  2377  
  2378  func testTransportCancelRequestInDo(t *testing.T, mode testMode, body io.Reader) {
  2379  	if testing.Short() {
  2380  		t.Skip("skipping test in -short mode")
  2381  	}
  2382  	unblockc := make(chan bool)
  2383  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2384  		<-unblockc
  2385  	})).ts
  2386  	defer close(unblockc)
  2387  
  2388  	c := ts.Client()
  2389  	tr := c.Transport.(*Transport)
  2390  
  2391  	donec := make(chan bool)
  2392  	req, _ := NewRequest("GET", ts.URL, body)
  2393  	go func() {
  2394  		defer close(donec)
  2395  		c.Do(req)
  2396  	}()
  2397  	start := time.Now()
  2398  	timeout := 10 * time.Second
  2399  	for time.Since(start) < timeout {
  2400  		time.Sleep(100 * time.Millisecond)
  2401  		tr.CancelRequest(req)
  2402  		select {
  2403  		case <-donec:
  2404  			return
  2405  		default:
  2406  		}
  2407  	}
  2408  	t.Errorf("Do of canceled request has not returned after %v", timeout)
  2409  }
  2410  
  2411  func TestTransportCancelRequestInDo(t *testing.T) {
  2412  	run(t, func(t *testing.T, mode testMode) {
  2413  		testTransportCancelRequestInDo(t, mode, nil)
  2414  	}, []testMode{http1Mode})
  2415  }
  2416  
  2417  func TestTransportCancelRequestWithBodyInDo(t *testing.T) {
  2418  	run(t, func(t *testing.T, mode testMode) {
  2419  		testTransportCancelRequestInDo(t, mode, bytes.NewBuffer([]byte{0}))
  2420  	}, []testMode{http1Mode})
  2421  }
  2422  
  2423  func TestTransportCancelRequestInDial(t *testing.T) {
  2424  	defer afterTest(t)
  2425  	if testing.Short() {
  2426  		t.Skip("skipping test in -short mode")
  2427  	}
  2428  	var logbuf strings.Builder
  2429  	eventLog := log.New(&logbuf, "", 0)
  2430  
  2431  	unblockDial := make(chan bool)
  2432  	defer close(unblockDial)
  2433  
  2434  	inDial := make(chan bool)
  2435  	tr := &Transport{
  2436  		Dial: func(network, addr string) (net.Conn, error) {
  2437  			eventLog.Println("dial: blocking")
  2438  			if !<-inDial {
  2439  				return nil, errors.New("main Test goroutine exited")
  2440  			}
  2441  			<-unblockDial
  2442  			return nil, errors.New("nope")
  2443  		},
  2444  	}
  2445  	cl := &Client{Transport: tr}
  2446  	gotres := make(chan bool)
  2447  	req, _ := NewRequest("GET", "http://something.no-network.tld/", nil)
  2448  	go func() {
  2449  		_, err := cl.Do(req)
  2450  		eventLog.Printf("Get = %v", err)
  2451  		gotres <- true
  2452  	}()
  2453  
  2454  	select {
  2455  	case inDial <- true:
  2456  	case <-time.After(5 * time.Second):
  2457  		close(inDial)
  2458  		t.Fatal("timeout; never saw blocking dial")
  2459  	}
  2460  
  2461  	eventLog.Printf("canceling")
  2462  	tr.CancelRequest(req)
  2463  	tr.CancelRequest(req) // used to panic on second call
  2464  
  2465  	select {
  2466  	case <-gotres:
  2467  	case <-time.After(5 * time.Second):
  2468  		panic("hang. events are: " + logbuf.String())
  2469  	}
  2470  
  2471  	got := logbuf.String()
  2472  	want := `dial: blocking
  2473  canceling
  2474  Get = Get "http://something.no-network.tld/": net/http: request canceled while waiting for connection
  2475  `
  2476  	if got != want {
  2477  		t.Errorf("Got events:\n%s\nWant:\n%s", got, want)
  2478  	}
  2479  }
  2480  
  2481  func TestCancelRequestWithChannel(t *testing.T) { run(t, testCancelRequestWithChannel) }
  2482  func testCancelRequestWithChannel(t *testing.T, mode testMode) {
  2483  	if testing.Short() {
  2484  		t.Skip("skipping test in -short mode")
  2485  	}
  2486  	unblockc := make(chan bool)
  2487  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2488  		fmt.Fprintf(w, "Hello")
  2489  		w.(Flusher).Flush() // send headers and some body
  2490  		<-unblockc
  2491  	})).ts
  2492  	defer close(unblockc)
  2493  
  2494  	c := ts.Client()
  2495  	tr := c.Transport.(*Transport)
  2496  
  2497  	req, _ := NewRequest("GET", ts.URL, nil)
  2498  	ch := make(chan struct{})
  2499  	req.Cancel = ch
  2500  
  2501  	res, err := c.Do(req)
  2502  	if err != nil {
  2503  		t.Fatal(err)
  2504  	}
  2505  	go func() {
  2506  		time.Sleep(1 * time.Second)
  2507  		close(ch)
  2508  	}()
  2509  	t0 := time.Now()
  2510  	body, err := io.ReadAll(res.Body)
  2511  	d := time.Since(t0)
  2512  
  2513  	if err != ExportErrRequestCanceled {
  2514  		t.Errorf("Body.Read error = %v; want errRequestCanceled", err)
  2515  	}
  2516  	if string(body) != "Hello" {
  2517  		t.Errorf("Body = %q; want Hello", body)
  2518  	}
  2519  	if d < 500*time.Millisecond {
  2520  		t.Errorf("expected ~1 second delay; got %v", d)
  2521  	}
  2522  	// Verify no outstanding requests after readLoop/writeLoop
  2523  	// goroutines shut down.
  2524  	for tries := 5; tries > 0; tries-- {
  2525  		n := tr.NumPendingRequestsForTesting()
  2526  		if n == 0 {
  2527  			break
  2528  		}
  2529  		time.Sleep(100 * time.Millisecond)
  2530  		if tries == 1 {
  2531  			t.Errorf("pending requests = %d; want 0", n)
  2532  		}
  2533  	}
  2534  }
  2535  
  2536  func TestCancelRequestWithChannelBeforeDo_Cancel(t *testing.T) {
  2537  	run(t, func(t *testing.T, mode testMode) {
  2538  		testCancelRequestWithChannelBeforeDo(t, mode, false)
  2539  	})
  2540  }
  2541  func TestCancelRequestWithChannelBeforeDo_Context(t *testing.T) {
  2542  	run(t, func(t *testing.T, mode testMode) {
  2543  		testCancelRequestWithChannelBeforeDo(t, mode, true)
  2544  	})
  2545  }
  2546  func testCancelRequestWithChannelBeforeDo(t *testing.T, mode testMode, withCtx bool) {
  2547  	unblockc := make(chan bool)
  2548  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2549  		<-unblockc
  2550  	})).ts
  2551  	defer close(unblockc)
  2552  
  2553  	c := ts.Client()
  2554  
  2555  	req, _ := NewRequest("GET", ts.URL, nil)
  2556  	if withCtx {
  2557  		ctx, cancel := context.WithCancel(context.Background())
  2558  		cancel()
  2559  		req = req.WithContext(ctx)
  2560  	} else {
  2561  		ch := make(chan struct{})
  2562  		req.Cancel = ch
  2563  		close(ch)
  2564  	}
  2565  
  2566  	_, err := c.Do(req)
  2567  	if ue, ok := err.(*url.Error); ok {
  2568  		err = ue.Err
  2569  	}
  2570  	if withCtx {
  2571  		if err != context.Canceled {
  2572  			t.Errorf("Do error = %v; want %v", err, context.Canceled)
  2573  		}
  2574  	} else {
  2575  		if err == nil || !strings.Contains(err.Error(), "canceled") {
  2576  			t.Errorf("Do error = %v; want cancellation", err)
  2577  		}
  2578  	}
  2579  }
  2580  
  2581  // Issue 11020. The returned error message should be errRequestCanceled
  2582  func TestTransportCancelBeforeResponseHeaders(t *testing.T) {
  2583  	defer afterTest(t)
  2584  
  2585  	serverConnCh := make(chan net.Conn, 1)
  2586  	tr := &Transport{
  2587  		Dial: func(network, addr string) (net.Conn, error) {
  2588  			cc, sc := net.Pipe()
  2589  			serverConnCh <- sc
  2590  			return cc, nil
  2591  		},
  2592  	}
  2593  	defer tr.CloseIdleConnections()
  2594  	errc := make(chan error, 1)
  2595  	req, _ := NewRequest("GET", "http://example.com/", nil)
  2596  	go func() {
  2597  		_, err := tr.RoundTrip(req)
  2598  		errc <- err
  2599  	}()
  2600  
  2601  	sc := <-serverConnCh
  2602  	verb := make([]byte, 3)
  2603  	if _, err := io.ReadFull(sc, verb); err != nil {
  2604  		t.Errorf("Error reading HTTP verb from server: %v", err)
  2605  	}
  2606  	if string(verb) != "GET" {
  2607  		t.Errorf("server received %q; want GET", verb)
  2608  	}
  2609  	defer sc.Close()
  2610  
  2611  	tr.CancelRequest(req)
  2612  
  2613  	err := <-errc
  2614  	if err == nil {
  2615  		t.Fatalf("unexpected success from RoundTrip")
  2616  	}
  2617  	if err != ExportErrRequestCanceled {
  2618  		t.Errorf("RoundTrip error = %v; want ExportErrRequestCanceled", err)
  2619  	}
  2620  }
  2621  
  2622  // golang.org/issue/3672 -- Client can't close HTTP stream
  2623  // Calling Close on a Response.Body used to just read until EOF.
  2624  // Now it actually closes the TCP connection.
  2625  func TestTransportCloseResponseBody(t *testing.T) { run(t, testTransportCloseResponseBody) }
  2626  func testTransportCloseResponseBody(t *testing.T, mode testMode) {
  2627  	writeErr := make(chan error, 1)
  2628  	msg := []byte("young\n")
  2629  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2630  		for {
  2631  			_, err := w.Write(msg)
  2632  			if err != nil {
  2633  				writeErr <- err
  2634  				return
  2635  			}
  2636  			w.(Flusher).Flush()
  2637  		}
  2638  	})).ts
  2639  
  2640  	c := ts.Client()
  2641  	tr := c.Transport.(*Transport)
  2642  
  2643  	req, _ := NewRequest("GET", ts.URL, nil)
  2644  	defer tr.CancelRequest(req)
  2645  
  2646  	res, err := c.Do(req)
  2647  	if err != nil {
  2648  		t.Fatal(err)
  2649  	}
  2650  
  2651  	const repeats = 3
  2652  	buf := make([]byte, len(msg)*repeats)
  2653  	want := bytes.Repeat(msg, repeats)
  2654  
  2655  	_, err = io.ReadFull(res.Body, buf)
  2656  	if err != nil {
  2657  		t.Fatal(err)
  2658  	}
  2659  	if !bytes.Equal(buf, want) {
  2660  		t.Fatalf("read %q; want %q", buf, want)
  2661  	}
  2662  	didClose := make(chan error, 1)
  2663  	go func() {
  2664  		didClose <- res.Body.Close()
  2665  	}()
  2666  	select {
  2667  	case err := <-didClose:
  2668  		if err != nil {
  2669  			t.Errorf("Close = %v", err)
  2670  		}
  2671  	case <-time.After(10 * time.Second):
  2672  		t.Fatal("too long waiting for close")
  2673  	}
  2674  	select {
  2675  	case err := <-writeErr:
  2676  		if err == nil {
  2677  			t.Errorf("expected non-nil write error")
  2678  		}
  2679  	case <-time.After(10 * time.Second):
  2680  		t.Fatal("too long waiting for write error")
  2681  	}
  2682  }
  2683  
  2684  type fooProto struct{}
  2685  
  2686  func (fooProto) RoundTrip(req *Request) (*Response, error) {
  2687  	res := &Response{
  2688  		Status:     "200 OK",
  2689  		StatusCode: 200,
  2690  		Header:     make(Header),
  2691  		Body:       io.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
  2692  	}
  2693  	return res, nil
  2694  }
  2695  
  2696  func TestTransportAltProto(t *testing.T) {
  2697  	defer afterTest(t)
  2698  	tr := &Transport{}
  2699  	c := &Client{Transport: tr}
  2700  	tr.RegisterProtocol("foo", fooProto{})
  2701  	res, err := c.Get("foo://bar.com/path")
  2702  	if err != nil {
  2703  		t.Fatal(err)
  2704  	}
  2705  	bodyb, err := io.ReadAll(res.Body)
  2706  	if err != nil {
  2707  		t.Fatal(err)
  2708  	}
  2709  	body := string(bodyb)
  2710  	if e := "You wanted foo://bar.com/path"; body != e {
  2711  		t.Errorf("got response %q, want %q", body, e)
  2712  	}
  2713  }
  2714  
  2715  func TestTransportNoHost(t *testing.T) {
  2716  	defer afterTest(t)
  2717  	tr := &Transport{}
  2718  	_, err := tr.RoundTrip(&Request{
  2719  		Header: make(Header),
  2720  		URL: &url.URL{
  2721  			Scheme: "http",
  2722  		},
  2723  	})
  2724  	want := "http: no Host in request URL"
  2725  	if got := fmt.Sprint(err); got != want {
  2726  		t.Errorf("error = %v; want %q", err, want)
  2727  	}
  2728  }
  2729  
  2730  // Issue 13311
  2731  func TestTransportEmptyMethod(t *testing.T) {
  2732  	req, _ := NewRequest("GET", "http://foo.com/", nil)
  2733  	req.Method = ""                                 // docs say "For client requests an empty string means GET"
  2734  	got, err := httputil.DumpRequestOut(req, false) // DumpRequestOut uses Transport
  2735  	if err != nil {
  2736  		t.Fatal(err)
  2737  	}
  2738  	if !strings.Contains(string(got), "GET ") {
  2739  		t.Fatalf("expected substring 'GET '; got: %s", got)
  2740  	}
  2741  }
  2742  
  2743  func TestTransportSocketLateBinding(t *testing.T) { run(t, testTransportSocketLateBinding) }
  2744  func testTransportSocketLateBinding(t *testing.T, mode testMode) {
  2745  	mux := NewServeMux()
  2746  	fooGate := make(chan bool, 1)
  2747  	mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) {
  2748  		w.Header().Set("foo-ipport", r.RemoteAddr)
  2749  		w.(Flusher).Flush()
  2750  		<-fooGate
  2751  	})
  2752  	mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) {
  2753  		w.Header().Set("bar-ipport", r.RemoteAddr)
  2754  	})
  2755  	ts := newClientServerTest(t, mode, mux).ts
  2756  
  2757  	dialGate := make(chan bool, 1)
  2758  	c := ts.Client()
  2759  	c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) {
  2760  		if <-dialGate {
  2761  			return net.Dial(n, addr)
  2762  		}
  2763  		return nil, errors.New("manually closed")
  2764  	}
  2765  
  2766  	dialGate <- true // only allow one dial
  2767  	fooRes, err := c.Get(ts.URL + "/foo")
  2768  	if err != nil {
  2769  		t.Fatal(err)
  2770  	}
  2771  	fooAddr := fooRes.Header.Get("foo-ipport")
  2772  	if fooAddr == "" {
  2773  		t.Fatal("No addr on /foo request")
  2774  	}
  2775  	time.AfterFunc(200*time.Millisecond, func() {
  2776  		// let the foo response finish so we can use its
  2777  		// connection for /bar
  2778  		fooGate <- true
  2779  		io.Copy(io.Discard, fooRes.Body)
  2780  		fooRes.Body.Close()
  2781  	})
  2782  
  2783  	barRes, err := c.Get(ts.URL + "/bar")
  2784  	if err != nil {
  2785  		t.Fatal(err)
  2786  	}
  2787  	barAddr := barRes.Header.Get("bar-ipport")
  2788  	if barAddr != fooAddr {
  2789  		t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr)
  2790  	}
  2791  	barRes.Body.Close()
  2792  	dialGate <- false
  2793  }
  2794  
  2795  // Issue 2184
  2796  func TestTransportReading100Continue(t *testing.T) {
  2797  	defer afterTest(t)
  2798  
  2799  	const numReqs = 5
  2800  	reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) }
  2801  	reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) }
  2802  
  2803  	send100Response := func(w *io.PipeWriter, r *io.PipeReader) {
  2804  		defer w.Close()
  2805  		defer r.Close()
  2806  		br := bufio.NewReader(r)
  2807  		n := 0
  2808  		for {
  2809  			n++
  2810  			req, err := ReadRequest(br)
  2811  			if err == io.EOF {
  2812  				return
  2813  			}
  2814  			if err != nil {
  2815  				t.Error(err)
  2816  				return
  2817  			}
  2818  			slurp, err := io.ReadAll(req.Body)
  2819  			if err != nil {
  2820  				t.Errorf("Server request body slurp: %v", err)
  2821  				return
  2822  			}
  2823  			id := req.Header.Get("Request-Id")
  2824  			resCode := req.Header.Get("X-Want-Response-Code")
  2825  			if resCode == "" {
  2826  				resCode = "100 Continue"
  2827  				if string(slurp) != reqBody(n) {
  2828  					t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n))
  2829  				}
  2830  			}
  2831  			body := fmt.Sprintf("Response number %d", n)
  2832  			v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s
  2833  Date: Thu, 28 Feb 2013 17:55:41 GMT
  2834  
  2835  HTTP/1.1 200 OK
  2836  Content-Type: text/html
  2837  Echo-Request-Id: %s
  2838  Content-Length: %d
  2839  
  2840  %s`, resCode, id, len(body), body), "\n", "\r\n", -1))
  2841  			w.Write(v)
  2842  			if id == reqID(numReqs) {
  2843  				return
  2844  			}
  2845  		}
  2846  
  2847  	}
  2848  
  2849  	tr := &Transport{
  2850  		Dial: func(n, addr string) (net.Conn, error) {
  2851  			sr, sw := io.Pipe() // server read/write
  2852  			cr, cw := io.Pipe() // client read/write
  2853  			conn := &rwTestConn{
  2854  				Reader: cr,
  2855  				Writer: sw,
  2856  				closeFunc: func() error {
  2857  					sw.Close()
  2858  					cw.Close()
  2859  					return nil
  2860  				},
  2861  			}
  2862  			go send100Response(cw, sr)
  2863  			return conn, nil
  2864  		},
  2865  		DisableKeepAlives: false,
  2866  	}
  2867  	defer tr.CloseIdleConnections()
  2868  	c := &Client{Transport: tr}
  2869  
  2870  	testResponse := func(req *Request, name string, wantCode int) {
  2871  		t.Helper()
  2872  		res, err := c.Do(req)
  2873  		if err != nil {
  2874  			t.Fatalf("%s: Do: %v", name, err)
  2875  		}
  2876  		if res.StatusCode != wantCode {
  2877  			t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode)
  2878  		}
  2879  		if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack {
  2880  			t.Errorf("%s: response id %q != request id %q", name, idBack, id)
  2881  		}
  2882  		_, err = io.ReadAll(res.Body)
  2883  		if err != nil {
  2884  			t.Fatalf("%s: Slurp error: %v", name, err)
  2885  		}
  2886  	}
  2887  
  2888  	// Few 100 responses, making sure we're not off-by-one.
  2889  	for i := 1; i <= numReqs; i++ {
  2890  		req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i)))
  2891  		req.Header.Set("Request-Id", reqID(i))
  2892  		testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200)
  2893  	}
  2894  }
  2895  
  2896  // Issue 17739: the HTTP client must ignore any unknown 1xx
  2897  // informational responses before the actual response.
  2898  func TestTransportIgnore1xxResponses(t *testing.T) {
  2899  	run(t, testTransportIgnore1xxResponses, []testMode{http1Mode})
  2900  }
  2901  func testTransportIgnore1xxResponses(t *testing.T, mode testMode) {
  2902  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2903  		conn, buf, _ := w.(Hijacker).Hijack()
  2904  		buf.Write([]byte("HTTP/1.1 123 OneTwoThree\r\nFoo: bar\r\n\r\nHTTP/1.1 200 OK\r\nBar: baz\r\nContent-Length: 5\r\n\r\nHello"))
  2905  		buf.Flush()
  2906  		conn.Close()
  2907  	}))
  2908  	cst.tr.DisableKeepAlives = true // prevent log spam; our test server is hanging up anyway
  2909  
  2910  	var got strings.Builder
  2911  
  2912  	req, _ := NewRequest("GET", cst.ts.URL, nil)
  2913  	req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
  2914  		Got1xxResponse: func(code int, header textproto.MIMEHeader) error {
  2915  			fmt.Fprintf(&got, "1xx: code=%v, header=%v\n", code, header)
  2916  			return nil
  2917  		},
  2918  	}))
  2919  	res, err := cst.c.Do(req)
  2920  	if err != nil {
  2921  		t.Fatal(err)
  2922  	}
  2923  	defer res.Body.Close()
  2924  
  2925  	res.Write(&got)
  2926  	want := "1xx: code=123, header=map[Foo:[bar]]\nHTTP/1.1 200 OK\r\nContent-Length: 5\r\nBar: baz\r\n\r\nHello"
  2927  	if got.String() != want {
  2928  		t.Errorf(" got: %q\nwant: %q\n", got.String(), want)
  2929  	}
  2930  }
  2931  
  2932  func TestTransportLimits1xxResponses(t *testing.T) {
  2933  	run(t, testTransportLimits1xxResponses, []testMode{http1Mode})
  2934  }
  2935  func testTransportLimits1xxResponses(t *testing.T, mode testMode) {
  2936  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2937  		conn, buf, _ := w.(Hijacker).Hijack()
  2938  		for i := 0; i < 10; i++ {
  2939  			buf.Write([]byte("HTTP/1.1 123 OneTwoThree\r\n\r\n"))
  2940  		}
  2941  		buf.Write([]byte("HTTP/1.1 204 No Content\r\n\r\n"))
  2942  		buf.Flush()
  2943  		conn.Close()
  2944  	}))
  2945  	cst.tr.DisableKeepAlives = true // prevent log spam; our test server is hanging up anyway
  2946  
  2947  	res, err := cst.c.Get(cst.ts.URL)
  2948  	if res != nil {
  2949  		defer res.Body.Close()
  2950  	}
  2951  	got := fmt.Sprint(err)
  2952  	wantSub := "too many 1xx informational responses"
  2953  	if !strings.Contains(got, wantSub) {
  2954  		t.Errorf("Get error = %v; want substring %q", err, wantSub)
  2955  	}
  2956  }
  2957  
  2958  // Issue 26161: the HTTP client must treat 101 responses
  2959  // as the final response.
  2960  func TestTransportTreat101Terminal(t *testing.T) {
  2961  	run(t, testTransportTreat101Terminal, []testMode{http1Mode})
  2962  }
  2963  func testTransportTreat101Terminal(t *testing.T, mode testMode) {
  2964  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  2965  		conn, buf, _ := w.(Hijacker).Hijack()
  2966  		buf.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n\r\n"))
  2967  		buf.Write([]byte("HTTP/1.1 204 No Content\r\n\r\n"))
  2968  		buf.Flush()
  2969  		conn.Close()
  2970  	}))
  2971  	res, err := cst.c.Get(cst.ts.URL)
  2972  	if err != nil {
  2973  		t.Fatal(err)
  2974  	}
  2975  	defer res.Body.Close()
  2976  	if res.StatusCode != StatusSwitchingProtocols {
  2977  		t.Errorf("StatusCode = %v; want 101 Switching Protocols", res.StatusCode)
  2978  	}
  2979  }
  2980  
  2981  type proxyFromEnvTest struct {
  2982  	req string // URL to fetch; blank means "http://example.com"
  2983  
  2984  	env      string // HTTP_PROXY
  2985  	httpsenv string // HTTPS_PROXY
  2986  	noenv    string // NO_PROXY
  2987  	reqmeth  string // REQUEST_METHOD
  2988  
  2989  	want    string
  2990  	wanterr error
  2991  }
  2992  
  2993  func (t proxyFromEnvTest) String() string {
  2994  	var buf strings.Builder
  2995  	space := func() {
  2996  		if buf.Len() > 0 {
  2997  			buf.WriteByte(' ')
  2998  		}
  2999  	}
  3000  	if t.env != "" {
  3001  		fmt.Fprintf(&buf, "http_proxy=%q", t.env)
  3002  	}
  3003  	if t.httpsenv != "" {
  3004  		space()
  3005  		fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv)
  3006  	}
  3007  	if t.noenv != "" {
  3008  		space()
  3009  		fmt.Fprintf(&buf, "no_proxy=%q", t.noenv)
  3010  	}
  3011  	if t.reqmeth != "" {
  3012  		space()
  3013  		fmt.Fprintf(&buf, "request_method=%q", t.reqmeth)
  3014  	}
  3015  	req := "http://example.com"
  3016  	if t.req != "" {
  3017  		req = t.req
  3018  	}
  3019  	space()
  3020  	fmt.Fprintf(&buf, "req=%q", req)
  3021  	return strings.TrimSpace(buf.String())
  3022  }
  3023  
  3024  var proxyFromEnvTests = []proxyFromEnvTest{
  3025  	{env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"},
  3026  	{env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"},
  3027  	{env: "cache.corp.example.com", want: "http://cache.corp.example.com"},
  3028  	{env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"},
  3029  	{env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"},
  3030  	{env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"},
  3031  	{env: "socks5://127.0.0.1", want: "socks5://127.0.0.1"},
  3032  
  3033  	// Don't use secure for http
  3034  	{req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"},
  3035  	// Use secure for https.
  3036  	{req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"},
  3037  	{req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"},
  3038  
  3039  	// Issue 16405: don't use HTTP_PROXY in a CGI environment,
  3040  	// where HTTP_PROXY can be attacker-controlled.
  3041  	{env: "http://10.1.2.3:8080", reqmeth: "POST",
  3042  		want:    "<nil>",
  3043  		wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")},
  3044  
  3045  	{want: "<nil>"},
  3046  
  3047  	{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
  3048  	{noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
  3049  	{noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
  3050  	{noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"},
  3051  	{noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
  3052  }
  3053  
  3054  func testProxyForRequest(t *testing.T, tt proxyFromEnvTest, proxyForRequest func(req *Request) (*url.URL, error)) {
  3055  	t.Helper()
  3056  	reqURL := tt.req
  3057  	if reqURL == "" {
  3058  		reqURL = "http://example.com"
  3059  	}
  3060  	req, _ := NewRequest("GET", reqURL, nil)
  3061  	url, err := proxyForRequest(req)
  3062  	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
  3063  		t.Errorf("%v: got error = %q, want %q", tt, g, e)
  3064  		return
  3065  	}
  3066  	if got := fmt.Sprintf("%s", url); got != tt.want {
  3067  		t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
  3068  	}
  3069  }
  3070  
  3071  func TestProxyFromEnvironment(t *testing.T) {
  3072  	ResetProxyEnv()
  3073  	defer ResetProxyEnv()
  3074  	for _, tt := range proxyFromEnvTests {
  3075  		testProxyForRequest(t, tt, func(req *Request) (*url.URL, error) {
  3076  			os.Setenv("HTTP_PROXY", tt.env)
  3077  			os.Setenv("HTTPS_PROXY", tt.httpsenv)
  3078  			os.Setenv("NO_PROXY", tt.noenv)
  3079  			os.Setenv("REQUEST_METHOD", tt.reqmeth)
  3080  			ResetCachedEnvironment()
  3081  			return ProxyFromEnvironment(req)
  3082  		})
  3083  	}
  3084  }
  3085  
  3086  func TestProxyFromEnvironmentLowerCase(t *testing.T) {
  3087  	ResetProxyEnv()
  3088  	defer ResetProxyEnv()
  3089  	for _, tt := range proxyFromEnvTests {
  3090  		testProxyForRequest(t, tt, func(req *Request) (*url.URL, error) {
  3091  			os.Setenv("http_proxy", tt.env)
  3092  			os.Setenv("https_proxy", tt.httpsenv)
  3093  			os.Setenv("no_proxy", tt.noenv)
  3094  			os.Setenv("REQUEST_METHOD", tt.reqmeth)
  3095  			ResetCachedEnvironment()
  3096  			return ProxyFromEnvironment(req)
  3097  		})
  3098  	}
  3099  }
  3100  
  3101  func TestIdleConnChannelLeak(t *testing.T) {
  3102  	run(t, testIdleConnChannelLeak, []testMode{http1Mode}, testNotParallel)
  3103  }
  3104  func testIdleConnChannelLeak(t *testing.T, mode testMode) {
  3105  	// Not parallel: uses global test hooks.
  3106  	var mu sync.Mutex
  3107  	var n int
  3108  
  3109  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3110  		mu.Lock()
  3111  		n++
  3112  		mu.Unlock()
  3113  	})).ts
  3114  
  3115  	const nReqs = 5
  3116  	didRead := make(chan bool, nReqs)
  3117  	SetReadLoopBeforeNextReadHook(func() { didRead <- true })
  3118  	defer SetReadLoopBeforeNextReadHook(nil)
  3119  
  3120  	c := ts.Client()
  3121  	tr := c.Transport.(*Transport)
  3122  	tr.Dial = func(netw, addr string) (net.Conn, error) {
  3123  		return net.Dial(netw, ts.Listener.Addr().String())
  3124  	}
  3125  
  3126  	// First, without keep-alives.
  3127  	for _, disableKeep := range []bool{true, false} {
  3128  		tr.DisableKeepAlives = disableKeep
  3129  		for i := 0; i < nReqs; i++ {
  3130  			_, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i))
  3131  			if err != nil {
  3132  				t.Fatal(err)
  3133  			}
  3134  			// Note: no res.Body.Close is needed here, since the
  3135  			// response Content-Length is zero. Perhaps the test
  3136  			// should be more explicit and use a HEAD, but tests
  3137  			// elsewhere guarantee that zero byte responses generate
  3138  			// a "Content-Length: 0" instead of chunking.
  3139  		}
  3140  
  3141  		// At this point, each of the 5 Transport.readLoop goroutines
  3142  		// are scheduling noting that there are no response bodies (see
  3143  		// earlier comment), and are then calling putIdleConn, which
  3144  		// decrements this count. Usually that happens quickly, which is
  3145  		// why this test has seemed to work for ages. But it's still
  3146  		// racey: we have wait for them to finish first. See Issue 10427
  3147  		for i := 0; i < nReqs; i++ {
  3148  			<-didRead
  3149  		}
  3150  
  3151  		if got := tr.IdleConnWaitMapSizeForTesting(); got != 0 {
  3152  			t.Fatalf("for DisableKeepAlives = %v, map size = %d; want 0", disableKeep, got)
  3153  		}
  3154  	}
  3155  }
  3156  
  3157  // Verify the status quo: that the Client.Post function coerces its
  3158  // body into a ReadCloser if it's a Closer, and that the Transport
  3159  // then closes it.
  3160  func TestTransportClosesRequestBody(t *testing.T) {
  3161  	run(t, testTransportClosesRequestBody, []testMode{http1Mode})
  3162  }
  3163  func testTransportClosesRequestBody(t *testing.T, mode testMode) {
  3164  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3165  		io.Copy(io.Discard, r.Body)
  3166  	})).ts
  3167  
  3168  	c := ts.Client()
  3169  
  3170  	closes := 0
  3171  
  3172  	res, err := c.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
  3173  	if err != nil {
  3174  		t.Fatal(err)
  3175  	}
  3176  	res.Body.Close()
  3177  	if closes != 1 {
  3178  		t.Errorf("closes = %d; want 1", closes)
  3179  	}
  3180  }
  3181  
  3182  func TestTransportTLSHandshakeTimeout(t *testing.T) {
  3183  	defer afterTest(t)
  3184  	if testing.Short() {
  3185  		t.Skip("skipping in short mode")
  3186  	}
  3187  	ln := newLocalListener(t)
  3188  	defer ln.Close()
  3189  	testdonec := make(chan struct{})
  3190  	defer close(testdonec)
  3191  
  3192  	go func() {
  3193  		c, err := ln.Accept()
  3194  		if err != nil {
  3195  			t.Error(err)
  3196  			return
  3197  		}
  3198  		<-testdonec
  3199  		c.Close()
  3200  	}()
  3201  
  3202  	getdonec := make(chan struct{})
  3203  	go func() {
  3204  		defer close(getdonec)
  3205  		tr := &Transport{
  3206  			Dial: func(_, _ string) (net.Conn, error) {
  3207  				return net.Dial("tcp", ln.Addr().String())
  3208  			},
  3209  			TLSHandshakeTimeout: 250 * time.Millisecond,
  3210  		}
  3211  		cl := &Client{Transport: tr}
  3212  		_, err := cl.Get("https://dummy.tld/")
  3213  		if err == nil {
  3214  			t.Error("expected error")
  3215  			return
  3216  		}
  3217  		ue, ok := err.(*url.Error)
  3218  		if !ok {
  3219  			t.Errorf("expected url.Error; got %#v", err)
  3220  			return
  3221  		}
  3222  		ne, ok := ue.Err.(net.Error)
  3223  		if !ok {
  3224  			t.Errorf("expected net.Error; got %#v", err)
  3225  			return
  3226  		}
  3227  		if !ne.Timeout() {
  3228  			t.Errorf("expected timeout error; got %v", err)
  3229  		}
  3230  		if !strings.Contains(err.Error(), "handshake timeout") {
  3231  			t.Errorf("expected 'handshake timeout' in error; got %v", err)
  3232  		}
  3233  	}()
  3234  	select {
  3235  	case <-getdonec:
  3236  	case <-time.After(5 * time.Second):
  3237  		t.Error("test timeout; TLS handshake hung?")
  3238  	}
  3239  }
  3240  
  3241  // Trying to repro golang.org/issue/3514
  3242  func TestTLSServerClosesConnection(t *testing.T) {
  3243  	run(t, testTLSServerClosesConnection, []testMode{https1Mode})
  3244  }
  3245  func testTLSServerClosesConnection(t *testing.T, mode testMode) {
  3246  	closedc := make(chan bool, 1)
  3247  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3248  		if strings.Contains(r.URL.Path, "/keep-alive-then-die") {
  3249  			conn, _, _ := w.(Hijacker).Hijack()
  3250  			conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo"))
  3251  			conn.Close()
  3252  			closedc <- true
  3253  			return
  3254  		}
  3255  		fmt.Fprintf(w, "hello")
  3256  	})).ts
  3257  
  3258  	c := ts.Client()
  3259  	tr := c.Transport.(*Transport)
  3260  
  3261  	var nSuccess = 0
  3262  	var errs []error
  3263  	const trials = 20
  3264  	for i := 0; i < trials; i++ {
  3265  		tr.CloseIdleConnections()
  3266  		res, err := c.Get(ts.URL + "/keep-alive-then-die")
  3267  		if err != nil {
  3268  			t.Fatal(err)
  3269  		}
  3270  		<-closedc
  3271  		slurp, err := io.ReadAll(res.Body)
  3272  		if err != nil {
  3273  			t.Fatal(err)
  3274  		}
  3275  		if string(slurp) != "foo" {
  3276  			t.Errorf("Got %q, want foo", slurp)
  3277  		}
  3278  
  3279  		// Now try again and see if we successfully
  3280  		// pick a new connection.
  3281  		res, err = c.Get(ts.URL + "/")
  3282  		if err != nil {
  3283  			errs = append(errs, err)
  3284  			continue
  3285  		}
  3286  		slurp, err = io.ReadAll(res.Body)
  3287  		if err != nil {
  3288  			errs = append(errs, err)
  3289  			continue
  3290  		}
  3291  		nSuccess++
  3292  	}
  3293  	if nSuccess > 0 {
  3294  		t.Logf("successes = %d of %d", nSuccess, trials)
  3295  	} else {
  3296  		t.Errorf("All runs failed:")
  3297  	}
  3298  	for _, err := range errs {
  3299  		t.Logf("  err: %v", err)
  3300  	}
  3301  }
  3302  
  3303  // byteFromChanReader is an io.Reader that reads a single byte at a
  3304  // time from the channel. When the channel is closed, the reader
  3305  // returns io.EOF.
  3306  type byteFromChanReader chan byte
  3307  
  3308  func (c byteFromChanReader) Read(p []byte) (n int, err error) {
  3309  	if len(p) == 0 {
  3310  		return
  3311  	}
  3312  	b, ok := <-c
  3313  	if !ok {
  3314  		return 0, io.EOF
  3315  	}
  3316  	p[0] = b
  3317  	return 1, nil
  3318  }
  3319  
  3320  // Verifies that the Transport doesn't reuse a connection in the case
  3321  // where the server replies before the request has been fully
  3322  // written. We still honor that reply (see TestIssue3595), but don't
  3323  // send future requests on the connection because it's then in a
  3324  // questionable state.
  3325  // golang.org/issue/7569
  3326  func TestTransportNoReuseAfterEarlyResponse(t *testing.T) {
  3327  	run(t, testTransportNoReuseAfterEarlyResponse, []testMode{http1Mode})
  3328  }
  3329  func testTransportNoReuseAfterEarlyResponse(t *testing.T, mode testMode) {
  3330  	var sconn struct {
  3331  		sync.Mutex
  3332  		c net.Conn
  3333  	}
  3334  	var getOkay bool
  3335  	closeConn := func() {
  3336  		sconn.Lock()
  3337  		defer sconn.Unlock()
  3338  		if sconn.c != nil {
  3339  			sconn.c.Close()
  3340  			sconn.c = nil
  3341  			if !getOkay {
  3342  				t.Logf("Closed server connection")
  3343  			}
  3344  		}
  3345  	}
  3346  	defer closeConn()
  3347  
  3348  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3349  		if r.Method == "GET" {
  3350  			io.WriteString(w, "bar")
  3351  			return
  3352  		}
  3353  		conn, _, _ := w.(Hijacker).Hijack()
  3354  		sconn.Lock()
  3355  		sconn.c = conn
  3356  		sconn.Unlock()
  3357  		conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive
  3358  		go io.Copy(io.Discard, conn)
  3359  	})).ts
  3360  	c := ts.Client()
  3361  
  3362  	const bodySize = 256 << 10
  3363  	finalBit := make(byteFromChanReader, 1)
  3364  	req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit))
  3365  	req.ContentLength = bodySize
  3366  	res, err := c.Do(req)
  3367  	if err := wantBody(res, err, "foo"); err != nil {
  3368  		t.Errorf("POST response: %v", err)
  3369  	}
  3370  	donec := make(chan bool)
  3371  	go func() {
  3372  		defer close(donec)
  3373  		res, err = c.Get(ts.URL)
  3374  		if err := wantBody(res, err, "bar"); err != nil {
  3375  			t.Errorf("GET response: %v", err)
  3376  			return
  3377  		}
  3378  		getOkay = true // suppress test noise
  3379  	}()
  3380  	time.AfterFunc(5*time.Second, closeConn)
  3381  	select {
  3382  	case <-donec:
  3383  		finalBit <- 'x' // unblock the writeloop of the first Post
  3384  		close(finalBit)
  3385  	case <-time.After(7 * time.Second):
  3386  		t.Fatal("timeout waiting for GET request to finish")
  3387  	}
  3388  }
  3389  
  3390  // Tests that we don't leak Transport persistConn.readLoop goroutines
  3391  // when a server hangs up immediately after saying it would keep-alive.
  3392  func TestTransportIssue10457(t *testing.T) { run(t, testTransportIssue10457, []testMode{http1Mode}) }
  3393  func testTransportIssue10457(t *testing.T, mode testMode) {
  3394  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3395  		// Send a response with no body, keep-alive
  3396  		// (implicit), and then lie and immediately close the
  3397  		// connection. This forces the Transport's readLoop to
  3398  		// immediately Peek an io.EOF and get to the point
  3399  		// that used to hang.
  3400  		conn, _, _ := w.(Hijacker).Hijack()
  3401  		conn.Write([]byte("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 0\r\n\r\n")) // keep-alive
  3402  		conn.Close()
  3403  	})).ts
  3404  	c := ts.Client()
  3405  
  3406  	res, err := c.Get(ts.URL)
  3407  	if err != nil {
  3408  		t.Fatalf("Get: %v", err)
  3409  	}
  3410  	defer res.Body.Close()
  3411  
  3412  	// Just a sanity check that we at least get the response. The real
  3413  	// test here is that the "defer afterTest" above doesn't find any
  3414  	// leaked goroutines.
  3415  	if got, want := res.Header.Get("Foo"), "Bar"; got != want {
  3416  		t.Errorf("Foo header = %q; want %q", got, want)
  3417  	}
  3418  }
  3419  
  3420  type closerFunc func() error
  3421  
  3422  func (f closerFunc) Close() error { return f() }
  3423  
  3424  type writerFuncConn struct {
  3425  	net.Conn
  3426  	write func(p []byte) (n int, err error)
  3427  }
  3428  
  3429  func (c writerFuncConn) Write(p []byte) (n int, err error) { return c.write(p) }
  3430  
  3431  // Issues 4677, 18241, and 17844. If we try to reuse a connection that the
  3432  // server is in the process of closing, we may end up successfully writing out
  3433  // our request (or a portion of our request) only to find a connection error
  3434  // when we try to read from (or finish writing to) the socket.
  3435  //
  3436  // NOTE: we resend a request only if:
  3437  //   - we reused a keep-alive connection
  3438  //   - we haven't yet received any header data
  3439  //   - either we wrote no bytes to the server, or the request is idempotent
  3440  //
  3441  // This automatically prevents an infinite resend loop because we'll run out of
  3442  // the cached keep-alive connections eventually.
  3443  func TestRetryRequestsOnError(t *testing.T) {
  3444  	run(t, testRetryRequestsOnError, testNotParallel, []testMode{http1Mode})
  3445  }
  3446  func testRetryRequestsOnError(t *testing.T, mode testMode) {
  3447  	newRequest := func(method, urlStr string, body io.Reader) *Request {
  3448  		req, err := NewRequest(method, urlStr, body)
  3449  		if err != nil {
  3450  			t.Fatal(err)
  3451  		}
  3452  		return req
  3453  	}
  3454  
  3455  	testCases := []struct {
  3456  		name       string
  3457  		failureN   int
  3458  		failureErr error
  3459  		// Note that we can't just re-use the Request object across calls to c.Do
  3460  		// because we need to rewind Body between calls.  (GetBody is only used to
  3461  		// rewind Body on failure and redirects, not just because it's done.)
  3462  		req       func() *Request
  3463  		reqString string
  3464  	}{
  3465  		{
  3466  			name: "IdempotentNoBodySomeWritten",
  3467  			// Believe that we've written some bytes to the server, so we know we're
  3468  			// not just in the "retry when no bytes sent" case".
  3469  			failureN: 1,
  3470  			// Use the specific error that shouldRetryRequest looks for with idempotent requests.
  3471  			failureErr: ExportErrServerClosedIdle,
  3472  			req: func() *Request {
  3473  				return newRequest("GET", "http://fake.golang", nil)
  3474  			},
  3475  			reqString: `GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n`,
  3476  		},
  3477  		{
  3478  			name: "IdempotentGetBodySomeWritten",
  3479  			// Believe that we've written some bytes to the server, so we know we're
  3480  			// not just in the "retry when no bytes sent" case".
  3481  			failureN: 1,
  3482  			// Use the specific error that shouldRetryRequest looks for with idempotent requests.
  3483  			failureErr: ExportErrServerClosedIdle,
  3484  			req: func() *Request {
  3485  				return newRequest("GET", "http://fake.golang", strings.NewReader("foo\n"))
  3486  			},
  3487  			reqString: `GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 4\r\nAccept-Encoding: gzip\r\n\r\nfoo\n`,
  3488  		},
  3489  		{
  3490  			name: "NothingWrittenNoBody",
  3491  			// It's key that we return 0 here -- that's what enables Transport to know
  3492  			// that nothing was written, even though this is a non-idempotent request.
  3493  			failureN:   0,
  3494  			failureErr: errors.New("second write fails"),
  3495  			req: func() *Request {
  3496  				return newRequest("DELETE", "http://fake.golang", nil)
  3497  			},
  3498  			reqString: `DELETE / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n`,
  3499  		},
  3500  		{
  3501  			name: "NothingWrittenGetBody",
  3502  			// It's key that we return 0 here -- that's what enables Transport to know
  3503  			// that nothing was written, even though this is a non-idempotent request.
  3504  			failureN:   0,
  3505  			failureErr: errors.New("second write fails"),
  3506  			// Note that NewRequest will set up GetBody for strings.Reader, which is
  3507  			// required for the retry to occur
  3508  			req: func() *Request {
  3509  				return newRequest("POST", "http://fake.golang", strings.NewReader("foo\n"))
  3510  			},
  3511  			reqString: `POST / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 4\r\nAccept-Encoding: gzip\r\n\r\nfoo\n`,
  3512  		},
  3513  	}
  3514  
  3515  	for _, tc := range testCases {
  3516  		t.Run(tc.name, func(t *testing.T) {
  3517  			var (
  3518  				mu     sync.Mutex
  3519  				logbuf strings.Builder
  3520  			)
  3521  			logf := func(format string, args ...any) {
  3522  				mu.Lock()
  3523  				defer mu.Unlock()
  3524  				fmt.Fprintf(&logbuf, format, args...)
  3525  				logbuf.WriteByte('\n')
  3526  			}
  3527  
  3528  			ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3529  				logf("Handler")
  3530  				w.Header().Set("X-Status", "ok")
  3531  			})).ts
  3532  
  3533  			var writeNumAtomic int32
  3534  			c := ts.Client()
  3535  			c.Transport.(*Transport).Dial = func(network, addr string) (net.Conn, error) {
  3536  				logf("Dial")
  3537  				c, err := net.Dial(network, ts.Listener.Addr().String())
  3538  				if err != nil {
  3539  					logf("Dial error: %v", err)
  3540  					return nil, err
  3541  				}
  3542  				return &writerFuncConn{
  3543  					Conn: c,
  3544  					write: func(p []byte) (n int, err error) {
  3545  						if atomic.AddInt32(&writeNumAtomic, 1) == 2 {
  3546  							logf("intentional write failure")
  3547  							return tc.failureN, tc.failureErr
  3548  						}
  3549  						logf("Write(%q)", p)
  3550  						return c.Write(p)
  3551  					},
  3552  				}, nil
  3553  			}
  3554  
  3555  			SetRoundTripRetried(func() {
  3556  				logf("Retried.")
  3557  			})
  3558  			defer SetRoundTripRetried(nil)
  3559  
  3560  			for i := 0; i < 3; i++ {
  3561  				t0 := time.Now()
  3562  				req := tc.req()
  3563  				res, err := c.Do(req)
  3564  				if err != nil {
  3565  					if time.Since(t0) < MaxWriteWaitBeforeConnReuse/2 {
  3566  						mu.Lock()
  3567  						got := logbuf.String()
  3568  						mu.Unlock()
  3569  						t.Fatalf("i=%d: Do = %v; log:\n%s", i, err, got)
  3570  					}
  3571  					t.Skipf("connection likely wasn't recycled within %d, interfering with actual test; skipping", MaxWriteWaitBeforeConnReuse)
  3572  				}
  3573  				res.Body.Close()
  3574  				if res.Request != req {
  3575  					t.Errorf("Response.Request != original request; want identical Request")
  3576  				}
  3577  			}
  3578  
  3579  			mu.Lock()
  3580  			got := logbuf.String()
  3581  			mu.Unlock()
  3582  			want := fmt.Sprintf(`Dial
  3583  Write("%s")
  3584  Handler
  3585  intentional write failure
  3586  Retried.
  3587  Dial
  3588  Write("%s")
  3589  Handler
  3590  Write("%s")
  3591  Handler
  3592  `, tc.reqString, tc.reqString, tc.reqString)
  3593  			if got != want {
  3594  				t.Errorf("Log of events differs. Got:\n%s\nWant:\n%s", got, want)
  3595  			}
  3596  		})
  3597  	}
  3598  }
  3599  
  3600  // Issue 6981
  3601  func TestTransportClosesBodyOnError(t *testing.T) { run(t, testTransportClosesBodyOnError) }
  3602  func testTransportClosesBodyOnError(t *testing.T, mode testMode) {
  3603  	readBody := make(chan error, 1)
  3604  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3605  		_, err := io.ReadAll(r.Body)
  3606  		readBody <- err
  3607  	})).ts
  3608  	c := ts.Client()
  3609  	fakeErr := errors.New("fake error")
  3610  	didClose := make(chan bool, 1)
  3611  	req, _ := NewRequest("POST", ts.URL, struct {
  3612  		io.Reader
  3613  		io.Closer
  3614  	}{
  3615  		io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), iotest.ErrReader(fakeErr)),
  3616  		closerFunc(func() error {
  3617  			select {
  3618  			case didClose <- true:
  3619  			default:
  3620  			}
  3621  			return nil
  3622  		}),
  3623  	})
  3624  	res, err := c.Do(req)
  3625  	if res != nil {
  3626  		defer res.Body.Close()
  3627  	}
  3628  	if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) {
  3629  		t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error())
  3630  	}
  3631  	select {
  3632  	case err := <-readBody:
  3633  		if err == nil {
  3634  			t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'")
  3635  		}
  3636  	case <-time.After(5 * time.Second):
  3637  		t.Error("timeout waiting for server handler to complete")
  3638  	}
  3639  	select {
  3640  	case <-didClose:
  3641  	default:
  3642  		t.Errorf("didn't see Body.Close")
  3643  	}
  3644  }
  3645  
  3646  func TestTransportDialTLS(t *testing.T) {
  3647  	run(t, testTransportDialTLS, []testMode{https1Mode, http2Mode})
  3648  }
  3649  func testTransportDialTLS(t *testing.T, mode testMode) {
  3650  	var mu sync.Mutex // guards following
  3651  	var gotReq, didDial bool
  3652  
  3653  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3654  		mu.Lock()
  3655  		gotReq = true
  3656  		mu.Unlock()
  3657  	})).ts
  3658  	c := ts.Client()
  3659  	c.Transport.(*Transport).DialTLS = func(netw, addr string) (net.Conn, error) {
  3660  		mu.Lock()
  3661  		didDial = true
  3662  		mu.Unlock()
  3663  		c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig)
  3664  		if err != nil {
  3665  			return nil, err
  3666  		}
  3667  		return c, c.Handshake()
  3668  	}
  3669  
  3670  	res, err := c.Get(ts.URL)
  3671  	if err != nil {
  3672  		t.Fatal(err)
  3673  	}
  3674  	res.Body.Close()
  3675  	mu.Lock()
  3676  	if !gotReq {
  3677  		t.Error("didn't get request")
  3678  	}
  3679  	if !didDial {
  3680  		t.Error("didn't use dial hook")
  3681  	}
  3682  }
  3683  
  3684  func TestTransportDialContext(t *testing.T) { run(t, testTransportDialContext) }
  3685  func testTransportDialContext(t *testing.T, mode testMode) {
  3686  	var mu sync.Mutex // guards following
  3687  	var gotReq bool
  3688  	var receivedContext context.Context
  3689  
  3690  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3691  		mu.Lock()
  3692  		gotReq = true
  3693  		mu.Unlock()
  3694  	})).ts
  3695  	c := ts.Client()
  3696  	c.Transport.(*Transport).DialContext = func(ctx context.Context, netw, addr string) (net.Conn, error) {
  3697  		mu.Lock()
  3698  		receivedContext = ctx
  3699  		mu.Unlock()
  3700  		return net.Dial(netw, addr)
  3701  	}
  3702  
  3703  	req, err := NewRequest("GET", ts.URL, nil)
  3704  	if err != nil {
  3705  		t.Fatal(err)
  3706  	}
  3707  	ctx := context.WithValue(context.Background(), "some-key", "some-value")
  3708  	res, err := c.Do(req.WithContext(ctx))
  3709  	if err != nil {
  3710  		t.Fatal(err)
  3711  	}
  3712  	res.Body.Close()
  3713  	mu.Lock()
  3714  	if !gotReq {
  3715  		t.Error("didn't get request")
  3716  	}
  3717  	if receivedContext != ctx {
  3718  		t.Error("didn't receive correct context")
  3719  	}
  3720  }
  3721  
  3722  func TestTransportDialTLSContext(t *testing.T) {
  3723  	run(t, testTransportDialTLSContext, []testMode{https1Mode, http2Mode})
  3724  }
  3725  func testTransportDialTLSContext(t *testing.T, mode testMode) {
  3726  	var mu sync.Mutex // guards following
  3727  	var gotReq bool
  3728  	var receivedContext context.Context
  3729  
  3730  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3731  		mu.Lock()
  3732  		gotReq = true
  3733  		mu.Unlock()
  3734  	})).ts
  3735  	c := ts.Client()
  3736  	c.Transport.(*Transport).DialTLSContext = func(ctx context.Context, netw, addr string) (net.Conn, error) {
  3737  		mu.Lock()
  3738  		receivedContext = ctx
  3739  		mu.Unlock()
  3740  		c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig)
  3741  		if err != nil {
  3742  			return nil, err
  3743  		}
  3744  		return c, c.HandshakeContext(ctx)
  3745  	}
  3746  
  3747  	req, err := NewRequest("GET", ts.URL, nil)
  3748  	if err != nil {
  3749  		t.Fatal(err)
  3750  	}
  3751  	ctx := context.WithValue(context.Background(), "some-key", "some-value")
  3752  	res, err := c.Do(req.WithContext(ctx))
  3753  	if err != nil {
  3754  		t.Fatal(err)
  3755  	}
  3756  	res.Body.Close()
  3757  	mu.Lock()
  3758  	if !gotReq {
  3759  		t.Error("didn't get request")
  3760  	}
  3761  	if receivedContext != ctx {
  3762  		t.Error("didn't receive correct context")
  3763  	}
  3764  }
  3765  
  3766  // Test for issue 8755
  3767  // Ensure that if a proxy returns an error, it is exposed by RoundTrip
  3768  func TestRoundTripReturnsProxyError(t *testing.T) {
  3769  	badProxy := func(*Request) (*url.URL, error) {
  3770  		return nil, errors.New("errorMessage")
  3771  	}
  3772  
  3773  	tr := &Transport{Proxy: badProxy}
  3774  
  3775  	req, _ := NewRequest("GET", "http://example.com", nil)
  3776  
  3777  	_, err := tr.RoundTrip(req)
  3778  
  3779  	if err == nil {
  3780  		t.Error("Expected proxy error to be returned by RoundTrip")
  3781  	}
  3782  }
  3783  
  3784  // tests that putting an idle conn after a call to CloseIdleConns does return it
  3785  func TestTransportCloseIdleConnsThenReturn(t *testing.T) {
  3786  	tr := &Transport{}
  3787  	wantIdle := func(when string, n int) bool {
  3788  		got := tr.IdleConnCountForTesting("http", "example.com") // key used by PutIdleTestConn
  3789  		if got == n {
  3790  			return true
  3791  		}
  3792  		t.Errorf("%s: idle conns = %d; want %d", when, got, n)
  3793  		return false
  3794  	}
  3795  	wantIdle("start", 0)
  3796  	if !tr.PutIdleTestConn("http", "example.com") {
  3797  		t.Fatal("put failed")
  3798  	}
  3799  	if !tr.PutIdleTestConn("http", "example.com") {
  3800  		t.Fatal("second put failed")
  3801  	}
  3802  	wantIdle("after put", 2)
  3803  	tr.CloseIdleConnections()
  3804  	if !tr.IsIdleForTesting() {
  3805  		t.Error("should be idle after CloseIdleConnections")
  3806  	}
  3807  	wantIdle("after close idle", 0)
  3808  	if tr.PutIdleTestConn("http", "example.com") {
  3809  		t.Fatal("put didn't fail")
  3810  	}
  3811  	wantIdle("after second put", 0)
  3812  
  3813  	tr.QueueForIdleConnForTesting() // should toggle the transport out of idle mode
  3814  	if tr.IsIdleForTesting() {
  3815  		t.Error("shouldn't be idle after QueueForIdleConnForTesting")
  3816  	}
  3817  	if !tr.PutIdleTestConn("http", "example.com") {
  3818  		t.Fatal("after re-activation")
  3819  	}
  3820  	wantIdle("after final put", 1)
  3821  }
  3822  
  3823  // Test for issue 34282
  3824  // Ensure that getConn doesn't call the GotConn trace hook on a HTTP/2 idle conn
  3825  func TestTransportTraceGotConnH2IdleConns(t *testing.T) {
  3826  	tr := &Transport{}
  3827  	wantIdle := func(when string, n int) bool {
  3828  		got := tr.IdleConnCountForTesting("https", "example.com:443") // key used by PutIdleTestConnH2
  3829  		if got == n {
  3830  			return true
  3831  		}
  3832  		t.Errorf("%s: idle conns = %d; want %d", when, got, n)
  3833  		return false
  3834  	}
  3835  	wantIdle("start", 0)
  3836  	alt := funcRoundTripper(func() {})
  3837  	if !tr.PutIdleTestConnH2("https", "example.com:443", alt) {
  3838  		t.Fatal("put failed")
  3839  	}
  3840  	wantIdle("after put", 1)
  3841  	ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
  3842  		GotConn: func(httptrace.GotConnInfo) {
  3843  			// tr.getConn should leave it for the HTTP/2 alt to call GotConn.
  3844  			t.Error("GotConn called")
  3845  		},
  3846  	})
  3847  	req, _ := NewRequestWithContext(ctx, MethodGet, "https://example.com", nil)
  3848  	_, err := tr.RoundTrip(req)
  3849  	if err != errFakeRoundTrip {
  3850  		t.Errorf("got error: %v; want %q", err, errFakeRoundTrip)
  3851  	}
  3852  	wantIdle("after round trip", 1)
  3853  }
  3854  
  3855  func TestTransportRemovesH2ConnsAfterIdle(t *testing.T) {
  3856  	run(t, testTransportRemovesH2ConnsAfterIdle, []testMode{http2Mode})
  3857  }
  3858  func testTransportRemovesH2ConnsAfterIdle(t *testing.T, mode testMode) {
  3859  	if testing.Short() {
  3860  		t.Skip("skipping in short mode")
  3861  	}
  3862  
  3863  	trFunc := func(tr *Transport) {
  3864  		tr.MaxConnsPerHost = 1
  3865  		tr.MaxIdleConnsPerHost = 1
  3866  		tr.IdleConnTimeout = 10 * time.Millisecond
  3867  	}
  3868  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), trFunc)
  3869  
  3870  	if _, err := cst.c.Get(cst.ts.URL); err != nil {
  3871  		t.Fatalf("got error: %s", err)
  3872  	}
  3873  
  3874  	time.Sleep(100 * time.Millisecond)
  3875  	got := make(chan error)
  3876  	go func() {
  3877  		if _, err := cst.c.Get(cst.ts.URL); err != nil {
  3878  			got <- err
  3879  		}
  3880  		close(got)
  3881  	}()
  3882  
  3883  	timeout := time.NewTimer(5 * time.Second)
  3884  	defer timeout.Stop()
  3885  	select {
  3886  	case err := <-got:
  3887  		if err != nil {
  3888  			t.Fatalf("got error: %s", err)
  3889  		}
  3890  	case <-timeout.C:
  3891  		t.Fatal("request never completed")
  3892  	}
  3893  }
  3894  
  3895  // This tests that a client requesting a content range won't also
  3896  // implicitly ask for gzip support. If they want that, they need to do it
  3897  // on their own.
  3898  // golang.org/issue/8923
  3899  func TestTransportRangeAndGzip(t *testing.T) { run(t, testTransportRangeAndGzip) }
  3900  func testTransportRangeAndGzip(t *testing.T, mode testMode) {
  3901  	reqc := make(chan *Request, 1)
  3902  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3903  		reqc <- r
  3904  	})).ts
  3905  	c := ts.Client()
  3906  
  3907  	req, _ := NewRequest("GET", ts.URL, nil)
  3908  	req.Header.Set("Range", "bytes=7-11")
  3909  	res, err := c.Do(req)
  3910  	if err != nil {
  3911  		t.Fatal(err)
  3912  	}
  3913  
  3914  	select {
  3915  	case r := <-reqc:
  3916  		if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
  3917  			t.Error("Transport advertised gzip support in the Accept header")
  3918  		}
  3919  		if r.Header.Get("Range") == "" {
  3920  			t.Error("no Range in request")
  3921  		}
  3922  	case <-time.After(10 * time.Second):
  3923  		t.Fatal("timeout")
  3924  	}
  3925  	res.Body.Close()
  3926  }
  3927  
  3928  // Test for issue 10474
  3929  func TestTransportResponseCancelRace(t *testing.T) { run(t, testTransportResponseCancelRace) }
  3930  func testTransportResponseCancelRace(t *testing.T, mode testMode) {
  3931  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3932  		// important that this response has a body.
  3933  		var b [1024]byte
  3934  		w.Write(b[:])
  3935  	})).ts
  3936  	tr := ts.Client().Transport.(*Transport)
  3937  
  3938  	req, err := NewRequest("GET", ts.URL, nil)
  3939  	if err != nil {
  3940  		t.Fatal(err)
  3941  	}
  3942  	res, err := tr.RoundTrip(req)
  3943  	if err != nil {
  3944  		t.Fatal(err)
  3945  	}
  3946  	// If we do an early close, Transport just throws the connection away and
  3947  	// doesn't reuse it. In order to trigger the bug, it has to reuse the connection
  3948  	// so read the body
  3949  	if _, err := io.Copy(io.Discard, res.Body); err != nil {
  3950  		t.Fatal(err)
  3951  	}
  3952  
  3953  	req2, err := NewRequest("GET", ts.URL, nil)
  3954  	if err != nil {
  3955  		t.Fatal(err)
  3956  	}
  3957  	tr.CancelRequest(req)
  3958  	res, err = tr.RoundTrip(req2)
  3959  	if err != nil {
  3960  		t.Fatal(err)
  3961  	}
  3962  	res.Body.Close()
  3963  }
  3964  
  3965  // Test for issue 19248: Content-Encoding's value is case insensitive.
  3966  func TestTransportContentEncodingCaseInsensitive(t *testing.T) {
  3967  	run(t, testTransportContentEncodingCaseInsensitive)
  3968  }
  3969  func testTransportContentEncodingCaseInsensitive(t *testing.T, mode testMode) {
  3970  	for _, ce := range []string{"gzip", "GZIP"} {
  3971  		ce := ce
  3972  		t.Run(ce, func(t *testing.T) {
  3973  			const encodedString = "Hello Gopher"
  3974  			ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  3975  				w.Header().Set("Content-Encoding", ce)
  3976  				gz := gzip.NewWriter(w)
  3977  				gz.Write([]byte(encodedString))
  3978  				gz.Close()
  3979  			})).ts
  3980  
  3981  			res, err := ts.Client().Get(ts.URL)
  3982  			if err != nil {
  3983  				t.Fatal(err)
  3984  			}
  3985  
  3986  			body, err := io.ReadAll(res.Body)
  3987  			res.Body.Close()
  3988  			if err != nil {
  3989  				t.Fatal(err)
  3990  			}
  3991  
  3992  			if string(body) != encodedString {
  3993  				t.Fatalf("Expected body %q, got: %q\n", encodedString, string(body))
  3994  			}
  3995  		})
  3996  	}
  3997  }
  3998  
  3999  func TestTransportDialCancelRace(t *testing.T) {
  4000  	run(t, testTransportDialCancelRace, testNotParallel, []testMode{http1Mode})
  4001  }
  4002  func testTransportDialCancelRace(t *testing.T, mode testMode) {
  4003  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {})).ts
  4004  	tr := ts.Client().Transport.(*Transport)
  4005  
  4006  	req, err := NewRequest("GET", ts.URL, nil)
  4007  	if err != nil {
  4008  		t.Fatal(err)
  4009  	}
  4010  	SetEnterRoundTripHook(func() {
  4011  		tr.CancelRequest(req)
  4012  	})
  4013  	defer SetEnterRoundTripHook(nil)
  4014  	res, err := tr.RoundTrip(req)
  4015  	if err != ExportErrRequestCanceled {
  4016  		t.Errorf("expected canceled request error; got %v", err)
  4017  		if err == nil {
  4018  			res.Body.Close()
  4019  		}
  4020  	}
  4021  }
  4022  
  4023  // logWritesConn is a net.Conn that logs each Write call to writes
  4024  // and then proxies to w.
  4025  // It proxies Read calls to a reader it receives from rch.
  4026  type logWritesConn struct {
  4027  	net.Conn // nil. crash on use.
  4028  
  4029  	w io.Writer
  4030  
  4031  	rch <-chan io.Reader
  4032  	r   io.Reader // nil until received by rch
  4033  
  4034  	mu     sync.Mutex
  4035  	writes []string
  4036  }
  4037  
  4038  func (c *logWritesConn) Write(p []byte) (n int, err error) {
  4039  	c.mu.Lock()
  4040  	defer c.mu.Unlock()
  4041  	c.writes = append(c.writes, string(p))
  4042  	return c.w.Write(p)
  4043  }
  4044  
  4045  func (c *logWritesConn) Read(p []byte) (n int, err error) {
  4046  	if c.r == nil {
  4047  		c.r = <-c.rch
  4048  	}
  4049  	return c.r.Read(p)
  4050  }
  4051  
  4052  func (c *logWritesConn) Close() error { return nil }
  4053  
  4054  // Issue 6574
  4055  func TestTransportFlushesBodyChunks(t *testing.T) {
  4056  	defer afterTest(t)
  4057  	resBody := make(chan io.Reader, 1)
  4058  	connr, connw := io.Pipe() // connection pipe pair
  4059  	lw := &logWritesConn{
  4060  		rch: resBody,
  4061  		w:   connw,
  4062  	}
  4063  	tr := &Transport{
  4064  		Dial: func(network, addr string) (net.Conn, error) {
  4065  			return lw, nil
  4066  		},
  4067  	}
  4068  	bodyr, bodyw := io.Pipe() // body pipe pair
  4069  	go func() {
  4070  		defer bodyw.Close()
  4071  		for i := 0; i < 3; i++ {
  4072  			fmt.Fprintf(bodyw, "num%d\n", i)
  4073  		}
  4074  	}()
  4075  	resc := make(chan *Response)
  4076  	go func() {
  4077  		req, _ := NewRequest("POST", "http://localhost:8080", bodyr)
  4078  		req.Header.Set("User-Agent", "x") // known value for test
  4079  		res, err := tr.RoundTrip(req)
  4080  		if err != nil {
  4081  			t.Errorf("RoundTrip: %v", err)
  4082  			close(resc)
  4083  			return
  4084  		}
  4085  		resc <- res
  4086  
  4087  	}()
  4088  	// Fully consume the request before checking the Write log vs. want.
  4089  	req, err := ReadRequest(bufio.NewReader(connr))
  4090  	if err != nil {
  4091  		t.Fatal(err)
  4092  	}
  4093  	io.Copy(io.Discard, req.Body)
  4094  
  4095  	// Unblock the transport's roundTrip goroutine.
  4096  	resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n")
  4097  	res, ok := <-resc
  4098  	if !ok {
  4099  		return
  4100  	}
  4101  	defer res.Body.Close()
  4102  
  4103  	want := []string{
  4104  		"POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n",
  4105  		"5\r\nnum0\n\r\n",
  4106  		"5\r\nnum1\n\r\n",
  4107  		"5\r\nnum2\n\r\n",
  4108  		"0\r\n\r\n",
  4109  	}
  4110  	if !reflect.DeepEqual(lw.writes, want) {
  4111  		t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want)
  4112  	}
  4113  }
  4114  
  4115  // Issue 22088: flush Transport request headers if we're not sure the body won't block on read.
  4116  func TestTransportFlushesRequestHeader(t *testing.T) { run(t, testTransportFlushesRequestHeader) }
  4117  func testTransportFlushesRequestHeader(t *testing.T, mode testMode) {
  4118  	gotReq := make(chan struct{})
  4119  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4120  		close(gotReq)
  4121  	}))
  4122  
  4123  	pr, pw := io.Pipe()
  4124  	req, err := NewRequest("POST", cst.ts.URL, pr)
  4125  	if err != nil {
  4126  		t.Fatal(err)
  4127  	}
  4128  	gotRes := make(chan struct{})
  4129  	go func() {
  4130  		defer close(gotRes)
  4131  		res, err := cst.tr.RoundTrip(req)
  4132  		if err != nil {
  4133  			t.Error(err)
  4134  			return
  4135  		}
  4136  		res.Body.Close()
  4137  	}()
  4138  
  4139  	select {
  4140  	case <-gotReq:
  4141  		pw.Close()
  4142  	case <-time.After(5 * time.Second):
  4143  		t.Fatal("timeout waiting for handler to get request")
  4144  	}
  4145  	<-gotRes
  4146  }
  4147  
  4148  // Issue 11745.
  4149  func TestTransportPrefersResponseOverWriteError(t *testing.T) {
  4150  	run(t, testTransportPrefersResponseOverWriteError)
  4151  }
  4152  func testTransportPrefersResponseOverWriteError(t *testing.T, mode testMode) {
  4153  	if testing.Short() {
  4154  		t.Skip("skipping in short mode")
  4155  	}
  4156  	const contentLengthLimit = 1024 * 1024 // 1MB
  4157  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4158  		if r.ContentLength >= contentLengthLimit {
  4159  			w.WriteHeader(StatusBadRequest)
  4160  			r.Body.Close()
  4161  			return
  4162  		}
  4163  		w.WriteHeader(StatusOK)
  4164  	})).ts
  4165  	c := ts.Client()
  4166  
  4167  	fail := 0
  4168  	count := 100
  4169  	bigBody := strings.Repeat("a", contentLengthLimit*2)
  4170  	for i := 0; i < count; i++ {
  4171  		req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody))
  4172  		if err != nil {
  4173  			t.Fatal(err)
  4174  		}
  4175  		resp, err := c.Do(req)
  4176  		if err != nil {
  4177  			fail++
  4178  			t.Logf("%d = %#v", i, err)
  4179  			if ue, ok := err.(*url.Error); ok {
  4180  				t.Logf("urlErr = %#v", ue.Err)
  4181  				if ne, ok := ue.Err.(*net.OpError); ok {
  4182  					t.Logf("netOpError = %#v", ne.Err)
  4183  				}
  4184  			}
  4185  		} else {
  4186  			resp.Body.Close()
  4187  			if resp.StatusCode != 400 {
  4188  				t.Errorf("Expected status code 400, got %v", resp.Status)
  4189  			}
  4190  		}
  4191  	}
  4192  	if fail > 0 {
  4193  		t.Errorf("Failed %v out of %v\n", fail, count)
  4194  	}
  4195  }
  4196  
  4197  func TestTransportAutomaticHTTP2(t *testing.T) {
  4198  	testTransportAutoHTTP(t, &Transport{}, true)
  4199  }
  4200  
  4201  func TestTransportAutomaticHTTP2_DialerAndTLSConfigSupportsHTTP2AndTLSConfig(t *testing.T) {
  4202  	testTransportAutoHTTP(t, &Transport{
  4203  		ForceAttemptHTTP2: true,
  4204  		TLSClientConfig:   new(tls.Config),
  4205  	}, true)
  4206  }
  4207  
  4208  // golang.org/issue/14391: also check DefaultTransport
  4209  func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) {
  4210  	testTransportAutoHTTP(t, DefaultTransport.(*Transport), true)
  4211  }
  4212  
  4213  func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) {
  4214  	testTransportAutoHTTP(t, &Transport{
  4215  		TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper),
  4216  	}, false)
  4217  }
  4218  
  4219  func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) {
  4220  	testTransportAutoHTTP(t, &Transport{
  4221  		TLSClientConfig: new(tls.Config),
  4222  	}, false)
  4223  }
  4224  
  4225  func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) {
  4226  	testTransportAutoHTTP(t, &Transport{
  4227  		ExpectContinueTimeout: 1 * time.Second,
  4228  	}, true)
  4229  }
  4230  
  4231  func TestTransportAutomaticHTTP2_Dial(t *testing.T) {
  4232  	var d net.Dialer
  4233  	testTransportAutoHTTP(t, &Transport{
  4234  		Dial: d.Dial,
  4235  	}, false)
  4236  }
  4237  
  4238  func TestTransportAutomaticHTTP2_DialContext(t *testing.T) {
  4239  	var d net.Dialer
  4240  	testTransportAutoHTTP(t, &Transport{
  4241  		DialContext: d.DialContext,
  4242  	}, false)
  4243  }
  4244  
  4245  func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) {
  4246  	testTransportAutoHTTP(t, &Transport{
  4247  		DialTLS: func(network, addr string) (net.Conn, error) {
  4248  			panic("unused")
  4249  		},
  4250  	}, false)
  4251  }
  4252  
  4253  func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) {
  4254  	CondSkipHTTP2(t)
  4255  	_, err := tr.RoundTrip(new(Request))
  4256  	if err == nil {
  4257  		t.Error("expected error from RoundTrip")
  4258  	}
  4259  	if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 {
  4260  		t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2)
  4261  	}
  4262  }
  4263  
  4264  // Issue 13633: there was a race where we returned bodyless responses
  4265  // to callers before recycling the persistent connection, which meant
  4266  // a client doing two subsequent requests could end up on different
  4267  // connections. It's somewhat harmless but enough tests assume it's
  4268  // not true in order to test other things that it's worth fixing.
  4269  // Plus it's nice to be consistent and not have timing-dependent
  4270  // behavior.
  4271  func TestTransportReuseConnEmptyResponseBody(t *testing.T) {
  4272  	run(t, testTransportReuseConnEmptyResponseBody)
  4273  }
  4274  func testTransportReuseConnEmptyResponseBody(t *testing.T, mode testMode) {
  4275  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4276  		w.Header().Set("X-Addr", r.RemoteAddr)
  4277  		// Empty response body.
  4278  	}))
  4279  	n := 100
  4280  	if testing.Short() {
  4281  		n = 10
  4282  	}
  4283  	var firstAddr string
  4284  	for i := 0; i < n; i++ {
  4285  		res, err := cst.c.Get(cst.ts.URL)
  4286  		if err != nil {
  4287  			log.Fatal(err)
  4288  		}
  4289  		addr := res.Header.Get("X-Addr")
  4290  		if i == 0 {
  4291  			firstAddr = addr
  4292  		} else if addr != firstAddr {
  4293  			t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr)
  4294  		}
  4295  		res.Body.Close()
  4296  	}
  4297  }
  4298  
  4299  // Issue 13839
  4300  func TestNoCrashReturningTransportAltConn(t *testing.T) {
  4301  	cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
  4302  	if err != nil {
  4303  		t.Fatal(err)
  4304  	}
  4305  	ln := newLocalListener(t)
  4306  	defer ln.Close()
  4307  
  4308  	var wg sync.WaitGroup
  4309  	SetPendingDialHooks(func() { wg.Add(1) }, wg.Done)
  4310  	defer SetPendingDialHooks(nil, nil)
  4311  
  4312  	testDone := make(chan struct{})
  4313  	defer close(testDone)
  4314  	go func() {
  4315  		tln := tls.NewListener(ln, &tls.Config{
  4316  			NextProtos:   []string{"foo"},
  4317  			Certificates: []tls.Certificate{cert},
  4318  		})
  4319  		sc, err := tln.Accept()
  4320  		if err != nil {
  4321  			t.Error(err)
  4322  			return
  4323  		}
  4324  		if err := sc.(*tls.Conn).Handshake(); err != nil {
  4325  			t.Error(err)
  4326  			return
  4327  		}
  4328  		<-testDone
  4329  		sc.Close()
  4330  	}()
  4331  
  4332  	addr := ln.Addr().String()
  4333  
  4334  	req, _ := NewRequest("GET", "https://fake.tld/", nil)
  4335  	cancel := make(chan struct{})
  4336  	req.Cancel = cancel
  4337  
  4338  	doReturned := make(chan bool, 1)
  4339  	madeRoundTripper := make(chan bool, 1)
  4340  
  4341  	tr := &Transport{
  4342  		DisableKeepAlives: true,
  4343  		TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{
  4344  			"foo": func(authority string, c *tls.Conn) RoundTripper {
  4345  				madeRoundTripper <- true
  4346  				return funcRoundTripper(func() {
  4347  					t.Error("foo RoundTripper should not be called")
  4348  				})
  4349  			},
  4350  		},
  4351  		Dial: func(_, _ string) (net.Conn, error) {
  4352  			panic("shouldn't be called")
  4353  		},
  4354  		DialTLS: func(_, _ string) (net.Conn, error) {
  4355  			tc, err := tls.Dial("tcp", addr, &tls.Config{
  4356  				InsecureSkipVerify: true,
  4357  				NextProtos:         []string{"foo"},
  4358  			})
  4359  			if err != nil {
  4360  				return nil, err
  4361  			}
  4362  			if err := tc.Handshake(); err != nil {
  4363  				return nil, err
  4364  			}
  4365  			close(cancel)
  4366  			<-doReturned
  4367  			return tc, nil
  4368  		},
  4369  	}
  4370  	c := &Client{Transport: tr}
  4371  
  4372  	_, err = c.Do(req)
  4373  	if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn {
  4374  		t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err)
  4375  	}
  4376  
  4377  	doReturned <- true
  4378  	<-madeRoundTripper
  4379  	wg.Wait()
  4380  }
  4381  
  4382  func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) {
  4383  	run(t, func(t *testing.T, mode testMode) {
  4384  		testTransportReuseConnection_Gzip(t, mode, true)
  4385  	})
  4386  }
  4387  
  4388  func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) {
  4389  	run(t, func(t *testing.T, mode testMode) {
  4390  		testTransportReuseConnection_Gzip(t, mode, false)
  4391  	})
  4392  }
  4393  
  4394  // Make sure we re-use underlying TCP connection for gzipped responses too.
  4395  func testTransportReuseConnection_Gzip(t *testing.T, mode testMode, chunked bool) {
  4396  	addr := make(chan string, 2)
  4397  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4398  		addr <- r.RemoteAddr
  4399  		w.Header().Set("Content-Encoding", "gzip")
  4400  		if chunked {
  4401  			w.(Flusher).Flush()
  4402  		}
  4403  		w.Write(rgz) // arbitrary gzip response
  4404  	})).ts
  4405  	c := ts.Client()
  4406  
  4407  	trace := &httptrace.ClientTrace{
  4408  		GetConn:      func(hostPort string) { t.Logf("GetConn(%q)", hostPort) },
  4409  		GotConn:      func(ci httptrace.GotConnInfo) { t.Logf("GotConn(%+v)", ci) },
  4410  		PutIdleConn:  func(err error) { t.Logf("PutIdleConn(%v)", err) },
  4411  		ConnectStart: func(network, addr string) { t.Logf("ConnectStart(%q, %q)", network, addr) },
  4412  		ConnectDone:  func(network, addr string, err error) { t.Logf("ConnectDone(%q, %q, %v)", network, addr, err) },
  4413  	}
  4414  	ctx := httptrace.WithClientTrace(context.Background(), trace)
  4415  
  4416  	for i := 0; i < 2; i++ {
  4417  		req, _ := NewRequest("GET", ts.URL, nil)
  4418  		req = req.WithContext(ctx)
  4419  		res, err := c.Do(req)
  4420  		if err != nil {
  4421  			t.Fatal(err)
  4422  		}
  4423  		buf := make([]byte, len(rgz))
  4424  		if n, err := io.ReadFull(res.Body, buf); err != nil {
  4425  			t.Errorf("%d. ReadFull = %v, %v", i, n, err)
  4426  		}
  4427  		// Note: no res.Body.Close call. It should work without it,
  4428  		// since the flate.Reader's internal buffering will hit EOF
  4429  		// and that should be sufficient.
  4430  	}
  4431  	a1, a2 := <-addr, <-addr
  4432  	if a1 != a2 {
  4433  		t.Fatalf("didn't reuse connection")
  4434  	}
  4435  }
  4436  
  4437  func TestTransportResponseHeaderLength(t *testing.T) { run(t, testTransportResponseHeaderLength) }
  4438  func testTransportResponseHeaderLength(t *testing.T, mode testMode) {
  4439  	if mode == http2Mode {
  4440  		t.Skip("HTTP/2 Transport doesn't support MaxResponseHeaderBytes")
  4441  	}
  4442  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4443  		if r.URL.Path == "/long" {
  4444  			w.Header().Set("Long", strings.Repeat("a", 1<<20))
  4445  		}
  4446  	})).ts
  4447  	c := ts.Client()
  4448  	c.Transport.(*Transport).MaxResponseHeaderBytes = 512 << 10
  4449  
  4450  	if res, err := c.Get(ts.URL); err != nil {
  4451  		t.Fatal(err)
  4452  	} else {
  4453  		res.Body.Close()
  4454  	}
  4455  
  4456  	res, err := c.Get(ts.URL + "/long")
  4457  	if err == nil {
  4458  		defer res.Body.Close()
  4459  		var n int64
  4460  		for k, vv := range res.Header {
  4461  			for _, v := range vv {
  4462  				n += int64(len(k)) + int64(len(v))
  4463  			}
  4464  		}
  4465  		t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n)
  4466  	}
  4467  	if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) {
  4468  		t.Errorf("got error: %v; want %q", err, want)
  4469  	}
  4470  }
  4471  
  4472  func TestTransportEventTrace(t *testing.T) {
  4473  	run(t, func(t *testing.T, mode testMode) {
  4474  		testTransportEventTrace(t, mode, false)
  4475  	}, testNotParallel)
  4476  }
  4477  
  4478  // test a non-nil httptrace.ClientTrace but with all hooks set to zero.
  4479  func TestTransportEventTrace_NoHooks(t *testing.T) {
  4480  	run(t, func(t *testing.T, mode testMode) {
  4481  		testTransportEventTrace(t, mode, true)
  4482  	}, testNotParallel)
  4483  }
  4484  
  4485  func testTransportEventTrace(t *testing.T, mode testMode, noHooks bool) {
  4486  	const resBody = "some body"
  4487  	gotWroteReqEvent := make(chan struct{}, 500)
  4488  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4489  		if r.Method == "GET" {
  4490  			// Do nothing for the second request.
  4491  			return
  4492  		}
  4493  		if _, err := io.ReadAll(r.Body); err != nil {
  4494  			t.Error(err)
  4495  		}
  4496  		if !noHooks {
  4497  			select {
  4498  			case <-gotWroteReqEvent:
  4499  			case <-time.After(5 * time.Second):
  4500  				t.Error("timeout waiting for WroteRequest event")
  4501  			}
  4502  		}
  4503  		io.WriteString(w, resBody)
  4504  	}), func(tr *Transport) {
  4505  		if tr.TLSClientConfig != nil {
  4506  			tr.TLSClientConfig.InsecureSkipVerify = true
  4507  		}
  4508  	})
  4509  	defer cst.close()
  4510  
  4511  	cst.tr.ExpectContinueTimeout = 1 * time.Second
  4512  
  4513  	var mu sync.Mutex // guards buf
  4514  	var buf strings.Builder
  4515  	logf := func(format string, args ...any) {
  4516  		mu.Lock()
  4517  		defer mu.Unlock()
  4518  		fmt.Fprintf(&buf, format, args...)
  4519  		buf.WriteByte('\n')
  4520  	}
  4521  
  4522  	addrStr := cst.ts.Listener.Addr().String()
  4523  	ip, port, err := net.SplitHostPort(addrStr)
  4524  	if err != nil {
  4525  		t.Fatal(err)
  4526  	}
  4527  
  4528  	// Install a fake DNS server.
  4529  	ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, network, host string) ([]net.IPAddr, error) {
  4530  		if host != "dns-is-faked.golang" {
  4531  			t.Errorf("unexpected DNS host lookup for %q/%q", network, host)
  4532  			return nil, nil
  4533  		}
  4534  		return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
  4535  	})
  4536  
  4537  	body := "some body"
  4538  	req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader(body))
  4539  	req.Header["X-Foo-Multiple-Vals"] = []string{"bar", "baz"}
  4540  	trace := &httptrace.ClientTrace{
  4541  		GetConn:              func(hostPort string) { logf("Getting conn for %v ...", hostPort) },
  4542  		GotConn:              func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) },
  4543  		GotFirstResponseByte: func() { logf("first response byte") },
  4544  		PutIdleConn:          func(err error) { logf("PutIdleConn = %v", err) },
  4545  		DNSStart:             func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) },
  4546  		DNSDone:              func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) },
  4547  		ConnectStart:         func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) },
  4548  		ConnectDone: func(network, addr string, err error) {
  4549  			if err != nil {
  4550  				t.Errorf("ConnectDone: %v", err)
  4551  			}
  4552  			logf("ConnectDone: connected to %s %s = %v", network, addr, err)
  4553  		},
  4554  		WroteHeaderField: func(key string, value []string) {
  4555  			logf("WroteHeaderField: %s: %v", key, value)
  4556  		},
  4557  		WroteHeaders: func() {
  4558  			logf("WroteHeaders")
  4559  		},
  4560  		Wait100Continue: func() { logf("Wait100Continue") },
  4561  		Got100Continue:  func() { logf("Got100Continue") },
  4562  		WroteRequest: func(e httptrace.WroteRequestInfo) {
  4563  			logf("WroteRequest: %+v", e)
  4564  			gotWroteReqEvent <- struct{}{}
  4565  		},
  4566  	}
  4567  	if mode == http2Mode {
  4568  		trace.TLSHandshakeStart = func() { logf("tls handshake start") }
  4569  		trace.TLSHandshakeDone = func(s tls.ConnectionState, err error) {
  4570  			logf("tls handshake done. ConnectionState = %v \n err = %v", s, err)
  4571  		}
  4572  	}
  4573  	if noHooks {
  4574  		// zero out all func pointers, trying to get some path to crash
  4575  		*trace = httptrace.ClientTrace{}
  4576  	}
  4577  	req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
  4578  
  4579  	req.Header.Set("Expect", "100-continue")
  4580  	res, err := cst.c.Do(req)
  4581  	if err != nil {
  4582  		t.Fatal(err)
  4583  	}
  4584  	logf("got roundtrip.response")
  4585  	slurp, err := io.ReadAll(res.Body)
  4586  	if err != nil {
  4587  		t.Fatal(err)
  4588  	}
  4589  	logf("consumed body")
  4590  	if string(slurp) != resBody || res.StatusCode != 200 {
  4591  		t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody)
  4592  	}
  4593  	res.Body.Close()
  4594  
  4595  	if noHooks {
  4596  		// Done at this point. Just testing a full HTTP
  4597  		// requests can happen with a trace pointing to a zero
  4598  		// ClientTrace, full of nil func pointers.
  4599  		return
  4600  	}
  4601  
  4602  	mu.Lock()
  4603  	got := buf.String()
  4604  	mu.Unlock()
  4605  
  4606  	wantOnce := func(sub string) {
  4607  		if strings.Count(got, sub) != 1 {
  4608  			t.Errorf("expected substring %q exactly once in output.", sub)
  4609  		}
  4610  	}
  4611  	wantOnceOrMore := func(sub string) {
  4612  		if strings.Count(got, sub) == 0 {
  4613  			t.Errorf("expected substring %q at least once in output.", sub)
  4614  		}
  4615  	}
  4616  	wantOnce("Getting conn for dns-is-faked.golang:" + port)
  4617  	wantOnce("DNS start: {Host:dns-is-faked.golang}")
  4618  	wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}")
  4619  	wantOnce("got conn: {")
  4620  	wantOnceOrMore("Connecting to tcp " + addrStr)
  4621  	wantOnceOrMore("connected to tcp " + addrStr + " = <nil>")
  4622  	wantOnce("Reused:false WasIdle:false IdleTime:0s")
  4623  	wantOnce("first response byte")
  4624  	if mode == http2Mode {
  4625  		wantOnce("tls handshake start")
  4626  		wantOnce("tls handshake done")
  4627  	} else {
  4628  		wantOnce("PutIdleConn = <nil>")
  4629  		wantOnce("WroteHeaderField: User-Agent: [Go-http-client/1.1]")
  4630  		// TODO(meirf): issue 19761. Make these agnostic to h1/h2. (These are not h1 specific, but the
  4631  		// WroteHeaderField hook is not yet implemented in h2.)
  4632  		wantOnce(fmt.Sprintf("WroteHeaderField: Host: [dns-is-faked.golang:%s]", port))
  4633  		wantOnce(fmt.Sprintf("WroteHeaderField: Content-Length: [%d]", len(body)))
  4634  		wantOnce("WroteHeaderField: X-Foo-Multiple-Vals: [bar baz]")
  4635  		wantOnce("WroteHeaderField: Accept-Encoding: [gzip]")
  4636  	}
  4637  	wantOnce("WroteHeaders")
  4638  	wantOnce("Wait100Continue")
  4639  	wantOnce("Got100Continue")
  4640  	wantOnce("WroteRequest: {Err:<nil>}")
  4641  	if strings.Contains(got, " to udp ") {
  4642  		t.Errorf("should not see UDP (DNS) connections")
  4643  	}
  4644  	if t.Failed() {
  4645  		t.Errorf("Output:\n%s", got)
  4646  	}
  4647  
  4648  	// And do a second request:
  4649  	req, _ = NewRequest("GET", cst.scheme()+"://dns-is-faked.golang:"+port, nil)
  4650  	req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
  4651  	res, err = cst.c.Do(req)
  4652  	if err != nil {
  4653  		t.Fatal(err)
  4654  	}
  4655  	if res.StatusCode != 200 {
  4656  		t.Fatal(res.Status)
  4657  	}
  4658  	res.Body.Close()
  4659  
  4660  	mu.Lock()
  4661  	got = buf.String()
  4662  	mu.Unlock()
  4663  
  4664  	sub := "Getting conn for dns-is-faked.golang:"
  4665  	if gotn, want := strings.Count(got, sub), 2; gotn != want {
  4666  		t.Errorf("substring %q appeared %d times; want %d. Log:\n%s", sub, gotn, want, got)
  4667  	}
  4668  
  4669  }
  4670  
  4671  func TestTransportEventTraceTLSVerify(t *testing.T) {
  4672  	run(t, testTransportEventTraceTLSVerify, []testMode{https1Mode, http2Mode})
  4673  }
  4674  func testTransportEventTraceTLSVerify(t *testing.T, mode testMode) {
  4675  	var mu sync.Mutex
  4676  	var buf strings.Builder
  4677  	logf := func(format string, args ...any) {
  4678  		mu.Lock()
  4679  		defer mu.Unlock()
  4680  		fmt.Fprintf(&buf, format, args...)
  4681  		buf.WriteByte('\n')
  4682  	}
  4683  
  4684  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4685  		t.Error("Unexpected request")
  4686  	}), func(ts *httptest.Server) {
  4687  		ts.Config.ErrorLog = log.New(funcWriter(func(p []byte) (int, error) {
  4688  			logf("%s", p)
  4689  			return len(p), nil
  4690  		}), "", 0)
  4691  	}).ts
  4692  
  4693  	certpool := x509.NewCertPool()
  4694  	certpool.AddCert(ts.Certificate())
  4695  
  4696  	c := &Client{Transport: &Transport{
  4697  		TLSClientConfig: &tls.Config{
  4698  			ServerName: "dns-is-faked.golang",
  4699  			RootCAs:    certpool,
  4700  		},
  4701  	}}
  4702  
  4703  	trace := &httptrace.ClientTrace{
  4704  		TLSHandshakeStart: func() { logf("TLSHandshakeStart") },
  4705  		TLSHandshakeDone: func(s tls.ConnectionState, err error) {
  4706  			logf("TLSHandshakeDone: ConnectionState = %v \n err = %v", s, err)
  4707  		},
  4708  	}
  4709  
  4710  	req, _ := NewRequest("GET", ts.URL, nil)
  4711  	req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
  4712  	_, err := c.Do(req)
  4713  	if err == nil {
  4714  		t.Error("Expected request to fail TLS verification")
  4715  	}
  4716  
  4717  	mu.Lock()
  4718  	got := buf.String()
  4719  	mu.Unlock()
  4720  
  4721  	wantOnce := func(sub string) {
  4722  		if strings.Count(got, sub) != 1 {
  4723  			t.Errorf("expected substring %q exactly once in output.", sub)
  4724  		}
  4725  	}
  4726  
  4727  	wantOnce("TLSHandshakeStart")
  4728  	wantOnce("TLSHandshakeDone")
  4729  	wantOnce("err = x509: certificate is valid for example.com")
  4730  
  4731  	if t.Failed() {
  4732  		t.Errorf("Output:\n%s", got)
  4733  	}
  4734  }
  4735  
  4736  var (
  4737  	isDNSHijackedOnce sync.Once
  4738  	isDNSHijacked     bool
  4739  )
  4740  
  4741  func skipIfDNSHijacked(t *testing.T) {
  4742  	// Skip this test if the user is using a shady/ISP
  4743  	// DNS server hijacking queries.
  4744  	// See issues 16732, 16716.
  4745  	isDNSHijackedOnce.Do(func() {
  4746  		addrs, _ := net.LookupHost("dns-should-not-resolve.golang")
  4747  		isDNSHijacked = len(addrs) != 0
  4748  	})
  4749  	if isDNSHijacked {
  4750  		t.Skip("skipping; test requires non-hijacking DNS server")
  4751  	}
  4752  }
  4753  
  4754  func TestTransportEventTraceRealDNS(t *testing.T) {
  4755  	skipIfDNSHijacked(t)
  4756  	defer afterTest(t)
  4757  	tr := &Transport{}
  4758  	defer tr.CloseIdleConnections()
  4759  	c := &Client{Transport: tr}
  4760  
  4761  	var mu sync.Mutex // guards buf
  4762  	var buf strings.Builder
  4763  	logf := func(format string, args ...any) {
  4764  		mu.Lock()
  4765  		defer mu.Unlock()
  4766  		fmt.Fprintf(&buf, format, args...)
  4767  		buf.WriteByte('\n')
  4768  	}
  4769  
  4770  	req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil)
  4771  	trace := &httptrace.ClientTrace{
  4772  		DNSStart:     func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) },
  4773  		DNSDone:      func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) },
  4774  		ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) },
  4775  		ConnectDone:  func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) },
  4776  	}
  4777  	req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
  4778  
  4779  	resp, err := c.Do(req)
  4780  	if err == nil {
  4781  		resp.Body.Close()
  4782  		t.Fatal("expected error during DNS lookup")
  4783  	}
  4784  
  4785  	mu.Lock()
  4786  	got := buf.String()
  4787  	mu.Unlock()
  4788  
  4789  	wantSub := func(sub string) {
  4790  		if !strings.Contains(got, sub) {
  4791  			t.Errorf("expected substring %q in output.", sub)
  4792  		}
  4793  	}
  4794  	wantSub("DNSStart: {Host:dns-should-not-resolve.golang}")
  4795  	wantSub("DNSDone: {Addrs:[] Err:")
  4796  	if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") {
  4797  		t.Errorf("should not see Connect events")
  4798  	}
  4799  	if t.Failed() {
  4800  		t.Errorf("Output:\n%s", got)
  4801  	}
  4802  }
  4803  
  4804  // Issue 14353: port can only contain digits.
  4805  func TestTransportRejectsAlphaPort(t *testing.T) {
  4806  	res, err := Get("http://dummy.tld:123foo/bar")
  4807  	if err == nil {
  4808  		res.Body.Close()
  4809  		t.Fatal("unexpected success")
  4810  	}
  4811  	ue, ok := err.(*url.Error)
  4812  	if !ok {
  4813  		t.Fatalf("got %#v; want *url.Error", err)
  4814  	}
  4815  	got := ue.Err.Error()
  4816  	want := `invalid port ":123foo" after host`
  4817  	if got != want {
  4818  		t.Errorf("got error %q; want %q", got, want)
  4819  	}
  4820  }
  4821  
  4822  // Test the httptrace.TLSHandshake{Start,Done} hooks with a https http1
  4823  // connections. The http2 test is done in TestTransportEventTrace_h2
  4824  func TestTLSHandshakeTrace(t *testing.T) {
  4825  	run(t, testTLSHandshakeTrace, []testMode{https1Mode, http2Mode})
  4826  }
  4827  func testTLSHandshakeTrace(t *testing.T, mode testMode) {
  4828  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {})).ts
  4829  
  4830  	var mu sync.Mutex
  4831  	var start, done bool
  4832  	trace := &httptrace.ClientTrace{
  4833  		TLSHandshakeStart: func() {
  4834  			mu.Lock()
  4835  			defer mu.Unlock()
  4836  			start = true
  4837  		},
  4838  		TLSHandshakeDone: func(s tls.ConnectionState, err error) {
  4839  			mu.Lock()
  4840  			defer mu.Unlock()
  4841  			done = true
  4842  			if err != nil {
  4843  				t.Fatal("Expected error to be nil but was:", err)
  4844  			}
  4845  		},
  4846  	}
  4847  
  4848  	c := ts.Client()
  4849  	req, err := NewRequest("GET", ts.URL, nil)
  4850  	if err != nil {
  4851  		t.Fatal("Unable to construct test request:", err)
  4852  	}
  4853  	req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
  4854  
  4855  	r, err := c.Do(req)
  4856  	if err != nil {
  4857  		t.Fatal("Unexpected error making request:", err)
  4858  	}
  4859  	r.Body.Close()
  4860  	mu.Lock()
  4861  	defer mu.Unlock()
  4862  	if !start {
  4863  		t.Fatal("Expected TLSHandshakeStart to be called, but wasn't")
  4864  	}
  4865  	if !done {
  4866  		t.Fatal("Expected TLSHandshakeDone to be called, but wasnt't")
  4867  	}
  4868  }
  4869  
  4870  func TestTransportMaxIdleConns(t *testing.T) {
  4871  	run(t, testTransportMaxIdleConns, []testMode{http1Mode})
  4872  }
  4873  func testTransportMaxIdleConns(t *testing.T, mode testMode) {
  4874  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4875  		// No body for convenience.
  4876  	})).ts
  4877  	c := ts.Client()
  4878  	tr := c.Transport.(*Transport)
  4879  	tr.MaxIdleConns = 4
  4880  
  4881  	ip, port, err := net.SplitHostPort(ts.Listener.Addr().String())
  4882  	if err != nil {
  4883  		t.Fatal(err)
  4884  	}
  4885  	ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, _, host string) ([]net.IPAddr, error) {
  4886  		return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
  4887  	})
  4888  
  4889  	hitHost := func(n int) {
  4890  		req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil)
  4891  		req = req.WithContext(ctx)
  4892  		res, err := c.Do(req)
  4893  		if err != nil {
  4894  			t.Fatal(err)
  4895  		}
  4896  		res.Body.Close()
  4897  	}
  4898  	for i := 0; i < 4; i++ {
  4899  		hitHost(i)
  4900  	}
  4901  	want := []string{
  4902  		"|http|host-0.dns-is-faked.golang:" + port,
  4903  		"|http|host-1.dns-is-faked.golang:" + port,
  4904  		"|http|host-2.dns-is-faked.golang:" + port,
  4905  		"|http|host-3.dns-is-faked.golang:" + port,
  4906  	}
  4907  	if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) {
  4908  		t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want)
  4909  	}
  4910  
  4911  	// Now hitting the 5th host should kick out the first host:
  4912  	hitHost(4)
  4913  	want = []string{
  4914  		"|http|host-1.dns-is-faked.golang:" + port,
  4915  		"|http|host-2.dns-is-faked.golang:" + port,
  4916  		"|http|host-3.dns-is-faked.golang:" + port,
  4917  		"|http|host-4.dns-is-faked.golang:" + port,
  4918  	}
  4919  	if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) {
  4920  		t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want)
  4921  	}
  4922  }
  4923  
  4924  func TestTransportIdleConnTimeout(t *testing.T) { run(t, testTransportIdleConnTimeout) }
  4925  func testTransportIdleConnTimeout(t *testing.T, mode testMode) {
  4926  	if testing.Short() {
  4927  		t.Skip("skipping in short mode")
  4928  	}
  4929  
  4930  	const timeout = 1 * time.Second
  4931  
  4932  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4933  		// No body for convenience.
  4934  	}))
  4935  	tr := cst.tr
  4936  	tr.IdleConnTimeout = timeout
  4937  	defer tr.CloseIdleConnections()
  4938  	c := &Client{Transport: tr}
  4939  
  4940  	idleConns := func() []string {
  4941  		if mode == http2Mode {
  4942  			return tr.IdleConnStrsForTesting_h2()
  4943  		} else {
  4944  			return tr.IdleConnStrsForTesting()
  4945  		}
  4946  	}
  4947  
  4948  	var conn string
  4949  	doReq := func(n int) {
  4950  		req, _ := NewRequest("GET", cst.ts.URL, nil)
  4951  		req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
  4952  			PutIdleConn: func(err error) {
  4953  				if err != nil {
  4954  					t.Errorf("failed to keep idle conn: %v", err)
  4955  				}
  4956  			},
  4957  		}))
  4958  		res, err := c.Do(req)
  4959  		if err != nil {
  4960  			t.Fatal(err)
  4961  		}
  4962  		res.Body.Close()
  4963  		conns := idleConns()
  4964  		if len(conns) != 1 {
  4965  			t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns)
  4966  		}
  4967  		if conn == "" {
  4968  			conn = conns[0]
  4969  		}
  4970  		if conn != conns[0] {
  4971  			t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n)
  4972  		}
  4973  	}
  4974  	for i := 0; i < 3; i++ {
  4975  		doReq(i)
  4976  		time.Sleep(timeout / 2)
  4977  	}
  4978  	time.Sleep(timeout * 3 / 2)
  4979  	if got := idleConns(); len(got) != 0 {
  4980  		t.Errorf("idle conns = %q; want none", got)
  4981  	}
  4982  }
  4983  
  4984  // Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an
  4985  // HTTP/2 connection was established but its caller no longer
  4986  // wanted it. (Assuming the connection cache was enabled, which it is
  4987  // by default)
  4988  //
  4989  // This test reproduced the crash by setting the IdleConnTimeout low
  4990  // (to make the test reasonable) and then making a request which is
  4991  // canceled by the DialTLS hook, which then also waits to return the
  4992  // real connection until after the RoundTrip saw the error.  Then we
  4993  // know the successful tls.Dial from DialTLS will need to go into the
  4994  // idle pool. Then we give it a of time to explode.
  4995  func TestIdleConnH2Crash(t *testing.T) { run(t, testIdleConnH2Crash, []testMode{http2Mode}) }
  4996  func testIdleConnH2Crash(t *testing.T, mode testMode) {
  4997  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  4998  		// nothing
  4999  	}))
  5000  
  5001  	ctx, cancel := context.WithCancel(context.Background())
  5002  	defer cancel()
  5003  
  5004  	sawDoErr := make(chan bool, 1)
  5005  	testDone := make(chan struct{})
  5006  	defer close(testDone)
  5007  
  5008  	cst.tr.IdleConnTimeout = 5 * time.Millisecond
  5009  	cst.tr.DialTLS = func(network, addr string) (net.Conn, error) {
  5010  		c, err := tls.Dial(network, addr, &tls.Config{
  5011  			InsecureSkipVerify: true,
  5012  			NextProtos:         []string{"h2"},
  5013  		})
  5014  		if err != nil {
  5015  			t.Error(err)
  5016  			return nil, err
  5017  		}
  5018  		if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" {
  5019  			t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2")
  5020  			c.Close()
  5021  			return nil, errors.New("bogus")
  5022  		}
  5023  
  5024  		cancel()
  5025  
  5026  		failTimer := time.NewTimer(5 * time.Second)
  5027  		defer failTimer.Stop()
  5028  		select {
  5029  		case <-sawDoErr:
  5030  		case <-testDone:
  5031  		case <-failTimer.C:
  5032  			t.Error("timeout in DialTLS, waiting too long for cst.c.Do to fail")
  5033  		}
  5034  		return c, nil
  5035  	}
  5036  
  5037  	req, _ := NewRequest("GET", cst.ts.URL, nil)
  5038  	req = req.WithContext(ctx)
  5039  	res, err := cst.c.Do(req)
  5040  	if err == nil {
  5041  		res.Body.Close()
  5042  		t.Fatal("unexpected success")
  5043  	}
  5044  	sawDoErr <- true
  5045  
  5046  	// Wait for the explosion.
  5047  	time.Sleep(cst.tr.IdleConnTimeout * 10)
  5048  }
  5049  
  5050  type funcConn struct {
  5051  	net.Conn
  5052  	read  func([]byte) (int, error)
  5053  	write func([]byte) (int, error)
  5054  }
  5055  
  5056  func (c funcConn) Read(p []byte) (int, error)  { return c.read(p) }
  5057  func (c funcConn) Write(p []byte) (int, error) { return c.write(p) }
  5058  func (c funcConn) Close() error                { return nil }
  5059  
  5060  // Issue 16465: Transport.RoundTrip should return the raw net.Conn.Read error from Peek
  5061  // back to the caller.
  5062  func TestTransportReturnsPeekError(t *testing.T) {
  5063  	errValue := errors.New("specific error value")
  5064  
  5065  	wrote := make(chan struct{})
  5066  	var wroteOnce sync.Once
  5067  
  5068  	tr := &Transport{
  5069  		Dial: func(network, addr string) (net.Conn, error) {
  5070  			c := funcConn{
  5071  				read: func([]byte) (int, error) {
  5072  					<-wrote
  5073  					return 0, errValue
  5074  				},
  5075  				write: func(p []byte) (int, error) {
  5076  					wroteOnce.Do(func() { close(wrote) })
  5077  					return len(p), nil
  5078  				},
  5079  			}
  5080  			return c, nil
  5081  		},
  5082  	}
  5083  	_, err := tr.RoundTrip(httptest.NewRequest("GET", "http://fake.tld/", nil))
  5084  	if err != errValue {
  5085  		t.Errorf("error = %#v; want %v", err, errValue)
  5086  	}
  5087  }
  5088  
  5089  // Issue 13835: international domain names should work
  5090  func TestTransportIDNA(t *testing.T) { run(t, testTransportIDNA) }
  5091  func testTransportIDNA(t *testing.T, mode testMode) {
  5092  	const uniDomain = "гофер.го"
  5093  	const punyDomain = "xn--c1ae0ajs.xn--c1aw"
  5094  
  5095  	var port string
  5096  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5097  		want := punyDomain + ":" + port
  5098  		if r.Host != want {
  5099  			t.Errorf("Host header = %q; want %q", r.Host, want)
  5100  		}
  5101  		if mode == http2Mode {
  5102  			if r.TLS == nil {
  5103  				t.Errorf("r.TLS == nil")
  5104  			} else if r.TLS.ServerName != punyDomain {
  5105  				t.Errorf("TLS.ServerName = %q; want %q", r.TLS.ServerName, punyDomain)
  5106  			}
  5107  		}
  5108  		w.Header().Set("Hit-Handler", "1")
  5109  	}), func(tr *Transport) {
  5110  		if tr.TLSClientConfig != nil {
  5111  			tr.TLSClientConfig.InsecureSkipVerify = true
  5112  		}
  5113  	})
  5114  
  5115  	ip, port, err := net.SplitHostPort(cst.ts.Listener.Addr().String())
  5116  	if err != nil {
  5117  		t.Fatal(err)
  5118  	}
  5119  
  5120  	// Install a fake DNS server.
  5121  	ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, network, host string) ([]net.IPAddr, error) {
  5122  		if host != punyDomain {
  5123  			t.Errorf("got DNS host lookup for %q/%q; want %q", network, host, punyDomain)
  5124  			return nil, nil
  5125  		}
  5126  		return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
  5127  	})
  5128  
  5129  	req, _ := NewRequest("GET", cst.scheme()+"://"+uniDomain+":"+port, nil)
  5130  	trace := &httptrace.ClientTrace{
  5131  		GetConn: func(hostPort string) {
  5132  			want := net.JoinHostPort(punyDomain, port)
  5133  			if hostPort != want {
  5134  				t.Errorf("getting conn for %q; want %q", hostPort, want)
  5135  			}
  5136  		},
  5137  		DNSStart: func(e httptrace.DNSStartInfo) {
  5138  			if e.Host != punyDomain {
  5139  				t.Errorf("DNSStart Host = %q; want %q", e.Host, punyDomain)
  5140  			}
  5141  		},
  5142  	}
  5143  	req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
  5144  
  5145  	res, err := cst.tr.RoundTrip(req)
  5146  	if err != nil {
  5147  		t.Fatal(err)
  5148  	}
  5149  	defer res.Body.Close()
  5150  	if res.Header.Get("Hit-Handler") != "1" {
  5151  		out, err := httputil.DumpResponse(res, true)
  5152  		if err != nil {
  5153  			t.Fatal(err)
  5154  		}
  5155  		t.Errorf("Response body wasn't from Handler. Got:\n%s\n", out)
  5156  	}
  5157  }
  5158  
  5159  // Issue 13290: send User-Agent in proxy CONNECT
  5160  func TestTransportProxyConnectHeader(t *testing.T) {
  5161  	run(t, testTransportProxyConnectHeader, []testMode{http1Mode})
  5162  }
  5163  func testTransportProxyConnectHeader(t *testing.T, mode testMode) {
  5164  	reqc := make(chan *Request, 1)
  5165  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5166  		if r.Method != "CONNECT" {
  5167  			t.Errorf("method = %q; want CONNECT", r.Method)
  5168  		}
  5169  		reqc <- r
  5170  		c, _, err := w.(Hijacker).Hijack()
  5171  		if err != nil {
  5172  			t.Errorf("Hijack: %v", err)
  5173  			return
  5174  		}
  5175  		c.Close()
  5176  	})).ts
  5177  
  5178  	c := ts.Client()
  5179  	c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) {
  5180  		return url.Parse(ts.URL)
  5181  	}
  5182  	c.Transport.(*Transport).ProxyConnectHeader = Header{
  5183  		"User-Agent": {"foo"},
  5184  		"Other":      {"bar"},
  5185  	}
  5186  
  5187  	res, err := c.Get("https://dummy.tld/") // https to force a CONNECT
  5188  	if err == nil {
  5189  		res.Body.Close()
  5190  		t.Errorf("unexpected success")
  5191  	}
  5192  	select {
  5193  	case <-time.After(3 * time.Second):
  5194  		t.Fatal("timeout")
  5195  	case r := <-reqc:
  5196  		if got, want := r.Header.Get("User-Agent"), "foo"; got != want {
  5197  			t.Errorf("CONNECT request User-Agent = %q; want %q", got, want)
  5198  		}
  5199  		if got, want := r.Header.Get("Other"), "bar"; got != want {
  5200  			t.Errorf("CONNECT request Other = %q; want %q", got, want)
  5201  		}
  5202  	}
  5203  }
  5204  
  5205  func TestTransportProxyGetConnectHeader(t *testing.T) {
  5206  	run(t, testTransportProxyGetConnectHeader, []testMode{http1Mode})
  5207  }
  5208  func testTransportProxyGetConnectHeader(t *testing.T, mode testMode) {
  5209  	reqc := make(chan *Request, 1)
  5210  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5211  		if r.Method != "CONNECT" {
  5212  			t.Errorf("method = %q; want CONNECT", r.Method)
  5213  		}
  5214  		reqc <- r
  5215  		c, _, err := w.(Hijacker).Hijack()
  5216  		if err != nil {
  5217  			t.Errorf("Hijack: %v", err)
  5218  			return
  5219  		}
  5220  		c.Close()
  5221  	})).ts
  5222  
  5223  	c := ts.Client()
  5224  	c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) {
  5225  		return url.Parse(ts.URL)
  5226  	}
  5227  	// These should be ignored:
  5228  	c.Transport.(*Transport).ProxyConnectHeader = Header{
  5229  		"User-Agent": {"foo"},
  5230  		"Other":      {"bar"},
  5231  	}
  5232  	c.Transport.(*Transport).GetProxyConnectHeader = func(ctx context.Context, proxyURL *url.URL, target string) (Header, error) {
  5233  		return Header{
  5234  			"User-Agent": {"foo2"},
  5235  			"Other":      {"bar2"},
  5236  		}, nil
  5237  	}
  5238  
  5239  	res, err := c.Get("https://dummy.tld/") // https to force a CONNECT
  5240  	if err == nil {
  5241  		res.Body.Close()
  5242  		t.Errorf("unexpected success")
  5243  	}
  5244  	select {
  5245  	case <-time.After(3 * time.Second):
  5246  		t.Fatal("timeout")
  5247  	case r := <-reqc:
  5248  		if got, want := r.Header.Get("User-Agent"), "foo2"; got != want {
  5249  			t.Errorf("CONNECT request User-Agent = %q; want %q", got, want)
  5250  		}
  5251  		if got, want := r.Header.Get("Other"), "bar2"; got != want {
  5252  			t.Errorf("CONNECT request Other = %q; want %q", got, want)
  5253  		}
  5254  	}
  5255  }
  5256  
  5257  var errFakeRoundTrip = errors.New("fake roundtrip")
  5258  
  5259  type funcRoundTripper func()
  5260  
  5261  func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) {
  5262  	fn()
  5263  	return nil, errFakeRoundTrip
  5264  }
  5265  
  5266  func wantBody(res *Response, err error, want string) error {
  5267  	if err != nil {
  5268  		return err
  5269  	}
  5270  	slurp, err := io.ReadAll(res.Body)
  5271  	if err != nil {
  5272  		return fmt.Errorf("error reading body: %v", err)
  5273  	}
  5274  	if string(slurp) != want {
  5275  		return fmt.Errorf("body = %q; want %q", slurp, want)
  5276  	}
  5277  	if err := res.Body.Close(); err != nil {
  5278  		return fmt.Errorf("body Close = %v", err)
  5279  	}
  5280  	return nil
  5281  }
  5282  
  5283  func newLocalListener(t *testing.T) net.Listener {
  5284  	ln, err := net.Listen("tcp", "127.0.0.1:0")
  5285  	if err != nil {
  5286  		ln, err = net.Listen("tcp6", "[::1]:0")
  5287  	}
  5288  	if err != nil {
  5289  		t.Fatal(err)
  5290  	}
  5291  	return ln
  5292  }
  5293  
  5294  type countCloseReader struct {
  5295  	n *int
  5296  	io.Reader
  5297  }
  5298  
  5299  func (cr countCloseReader) Close() error {
  5300  	(*cr.n)++
  5301  	return nil
  5302  }
  5303  
  5304  // rgz is a gzip quine that uncompresses to itself.
  5305  var rgz = []byte{
  5306  	0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
  5307  	0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73,
  5308  	0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0,
  5309  	0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2,
  5310  	0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17,
  5311  	0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60,
  5312  	0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2,
  5313  	0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00,
  5314  	0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00,
  5315  	0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16,
  5316  	0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05,
  5317  	0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff,
  5318  	0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00,
  5319  	0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00,
  5320  	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
  5321  	0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88,
  5322  	0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff,
  5323  	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00,
  5324  	0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00,
  5325  	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
  5326  	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  5327  	0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff,
  5328  	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00,
  5329  	0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
  5330  	0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16,
  5331  	0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08,
  5332  	0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa,
  5333  	0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06,
  5334  	0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00,
  5335  	0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
  5336  	0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
  5337  	0x00, 0x00,
  5338  }
  5339  
  5340  // Ensure that a missing status doesn't make the server panic
  5341  // See Issue https://golang.org/issues/21701
  5342  func TestMissingStatusNoPanic(t *testing.T) {
  5343  	t.Parallel()
  5344  
  5345  	const want = "unknown status code"
  5346  
  5347  	ln := newLocalListener(t)
  5348  	addr := ln.Addr().String()
  5349  	done := make(chan bool)
  5350  	fullAddrURL := fmt.Sprintf("http://%s", addr)
  5351  	raw := "HTTP/1.1 400\r\n" +
  5352  		"Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" +
  5353  		"Content-Type: text/html; charset=utf-8\r\n" +
  5354  		"Content-Length: 10\r\n" +
  5355  		"Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT\r\n" +
  5356  		"Vary: Accept-Encoding\r\n\r\n" +
  5357  		"Aloha Olaa"
  5358  
  5359  	go func() {
  5360  		defer close(done)
  5361  
  5362  		conn, _ := ln.Accept()
  5363  		if conn != nil {
  5364  			io.WriteString(conn, raw)
  5365  			io.ReadAll(conn)
  5366  			conn.Close()
  5367  		}
  5368  	}()
  5369  
  5370  	proxyURL, err := url.Parse(fullAddrURL)
  5371  	if err != nil {
  5372  		t.Fatalf("proxyURL: %v", err)
  5373  	}
  5374  
  5375  	tr := &Transport{Proxy: ProxyURL(proxyURL)}
  5376  
  5377  	req, _ := NewRequest("GET", "https://golang.org/", nil)
  5378  	res, err, panicked := doFetchCheckPanic(tr, req)
  5379  	if panicked {
  5380  		t.Error("panicked, expecting an error")
  5381  	}
  5382  	if res != nil && res.Body != nil {
  5383  		io.Copy(io.Discard, res.Body)
  5384  		res.Body.Close()
  5385  	}
  5386  
  5387  	if err == nil || !strings.Contains(err.Error(), want) {
  5388  		t.Errorf("got=%v want=%q", err, want)
  5389  	}
  5390  
  5391  	ln.Close()
  5392  	<-done
  5393  }
  5394  
  5395  func doFetchCheckPanic(tr *Transport, req *Request) (res *Response, err error, panicked bool) {
  5396  	defer func() {
  5397  		if r := recover(); r != nil {
  5398  			panicked = true
  5399  		}
  5400  	}()
  5401  	res, err = tr.RoundTrip(req)
  5402  	return
  5403  }
  5404  
  5405  // Issue 22330: do not allow the response body to be read when the status code
  5406  // forbids a response body.
  5407  func TestNoBodyOnChunked304Response(t *testing.T) {
  5408  	run(t, testNoBodyOnChunked304Response, []testMode{http1Mode})
  5409  }
  5410  func testNoBodyOnChunked304Response(t *testing.T, mode testMode) {
  5411  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5412  		conn, buf, _ := w.(Hijacker).Hijack()
  5413  		buf.Write([]byte("HTTP/1.1 304 NOT MODIFIED\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n"))
  5414  		buf.Flush()
  5415  		conn.Close()
  5416  	}))
  5417  
  5418  	// Our test server above is sending back bogus data after the
  5419  	// response (the "0\r\n\r\n" part), which causes the Transport
  5420  	// code to log spam. Disable keep-alives so we never even try
  5421  	// to reuse the connection.
  5422  	cst.tr.DisableKeepAlives = true
  5423  
  5424  	res, err := cst.c.Get(cst.ts.URL)
  5425  	if err != nil {
  5426  		t.Fatal(err)
  5427  	}
  5428  
  5429  	if res.Body != NoBody {
  5430  		t.Errorf("Unexpected body on 304 response")
  5431  	}
  5432  }
  5433  
  5434  type funcWriter func([]byte) (int, error)
  5435  
  5436  func (f funcWriter) Write(p []byte) (int, error) { return f(p) }
  5437  
  5438  type doneContext struct {
  5439  	context.Context
  5440  	err error
  5441  }
  5442  
  5443  func (doneContext) Done() <-chan struct{} {
  5444  	c := make(chan struct{})
  5445  	close(c)
  5446  	return c
  5447  }
  5448  
  5449  func (d doneContext) Err() error { return d.err }
  5450  
  5451  // Issue 25852: Transport should check whether Context is done early.
  5452  func TestTransportCheckContextDoneEarly(t *testing.T) {
  5453  	tr := &Transport{}
  5454  	req, _ := NewRequest("GET", "http://fake.example/", nil)
  5455  	wantErr := errors.New("some error")
  5456  	req = req.WithContext(doneContext{context.Background(), wantErr})
  5457  	_, err := tr.RoundTrip(req)
  5458  	if err != wantErr {
  5459  		t.Errorf("error = %v; want %v", err, wantErr)
  5460  	}
  5461  }
  5462  
  5463  // Issue 23399: verify that if a client request times out, the Transport's
  5464  // conn is closed so that it's not reused.
  5465  //
  5466  // This is the test variant that times out before the server replies with
  5467  // any response headers.
  5468  func TestClientTimeoutKillsConn_BeforeHeaders(t *testing.T) {
  5469  	run(t, testClientTimeoutKillsConn_BeforeHeaders, []testMode{http1Mode})
  5470  }
  5471  func testClientTimeoutKillsConn_BeforeHeaders(t *testing.T, mode testMode) {
  5472  	inHandler := make(chan net.Conn, 1)
  5473  	handlerReadReturned := make(chan bool, 1)
  5474  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5475  		conn, _, err := w.(Hijacker).Hijack()
  5476  		if err != nil {
  5477  			t.Error(err)
  5478  			return
  5479  		}
  5480  		inHandler <- conn
  5481  		n, err := conn.Read([]byte{0})
  5482  		if n != 0 || err != io.EOF {
  5483  			t.Errorf("unexpected Read result: %v, %v", n, err)
  5484  		}
  5485  		handlerReadReturned <- true
  5486  	}))
  5487  
  5488  	const timeout = 50 * time.Millisecond
  5489  	cst.c.Timeout = timeout
  5490  
  5491  	_, err := cst.c.Get(cst.ts.URL)
  5492  	if err == nil {
  5493  		t.Fatal("unexpected Get succeess")
  5494  	}
  5495  
  5496  	select {
  5497  	case c := <-inHandler:
  5498  		select {
  5499  		case <-handlerReadReturned:
  5500  			// Success.
  5501  			return
  5502  		case <-time.After(5 * time.Second):
  5503  			t.Error("Handler's conn.Read seems to be stuck in Read")
  5504  			c.Close() // close it to unblock Handler
  5505  		}
  5506  	case <-time.After(timeout * 10):
  5507  		// If we didn't get into the Handler in 50ms, that probably means
  5508  		// the builder was just slow and the Get failed in that time
  5509  		// but never made it to the server. That's fine. We'll usually
  5510  		// test the part above on faster machines.
  5511  		t.Skip("skipping test on slow builder")
  5512  	}
  5513  }
  5514  
  5515  // Issue 23399: verify that if a client request times out, the Transport's
  5516  // conn is closed so that it's not reused.
  5517  //
  5518  // This is the test variant that has the server send response headers
  5519  // first, and time out during the write of the response body.
  5520  func TestClientTimeoutKillsConn_AfterHeaders(t *testing.T) {
  5521  	run(t, testClientTimeoutKillsConn_AfterHeaders, []testMode{http1Mode})
  5522  }
  5523  func testClientTimeoutKillsConn_AfterHeaders(t *testing.T, mode testMode) {
  5524  	inHandler := make(chan net.Conn, 1)
  5525  	handlerResult := make(chan error, 1)
  5526  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5527  		w.Header().Set("Content-Length", "100")
  5528  		w.(Flusher).Flush()
  5529  		conn, _, err := w.(Hijacker).Hijack()
  5530  		if err != nil {
  5531  			t.Error(err)
  5532  			return
  5533  		}
  5534  		conn.Write([]byte("foo"))
  5535  		inHandler <- conn
  5536  		n, err := conn.Read([]byte{0})
  5537  		// The error should be io.EOF or "read tcp
  5538  		// 127.0.0.1:35827->127.0.0.1:40290: read: connection
  5539  		// reset by peer" depending on timing. Really we just
  5540  		// care that it returns at all. But if it returns with
  5541  		// data, that's weird.
  5542  		if n != 0 || err == nil {
  5543  			handlerResult <- fmt.Errorf("unexpected Read result: %v, %v", n, err)
  5544  			return
  5545  		}
  5546  		handlerResult <- nil
  5547  	}))
  5548  
  5549  	// Set Timeout to something very long but non-zero to exercise
  5550  	// the codepaths that check for it. But rather than wait for it to fire
  5551  	// (which would make the test slow), we send on the req.Cancel channel instead,
  5552  	// which happens to exercise the same code paths.
  5553  	cst.c.Timeout = time.Minute // just to be non-zero, not to hit it.
  5554  	req, _ := NewRequest("GET", cst.ts.URL, nil)
  5555  	cancel := make(chan struct{})
  5556  	req.Cancel = cancel
  5557  
  5558  	res, err := cst.c.Do(req)
  5559  	if err != nil {
  5560  		select {
  5561  		case <-inHandler:
  5562  			t.Fatalf("Get error: %v", err)
  5563  		default:
  5564  			// Failed before entering handler. Ignore result.
  5565  			t.Skip("skipping test on slow builder")
  5566  		}
  5567  	}
  5568  
  5569  	close(cancel)
  5570  	got, err := io.ReadAll(res.Body)
  5571  	if err == nil {
  5572  		t.Fatalf("unexpected success; read %q, nil", got)
  5573  	}
  5574  
  5575  	select {
  5576  	case c := <-inHandler:
  5577  		select {
  5578  		case err := <-handlerResult:
  5579  			if err != nil {
  5580  				t.Errorf("handler: %v", err)
  5581  			}
  5582  			return
  5583  		case <-time.After(5 * time.Second):
  5584  			t.Error("Handler's conn.Read seems to be stuck in Read")
  5585  			c.Close() // close it to unblock Handler
  5586  		}
  5587  	case <-time.After(5 * time.Second):
  5588  		t.Fatal("timeout")
  5589  	}
  5590  }
  5591  
  5592  func TestTransportResponseBodyWritableOnProtocolSwitch(t *testing.T) {
  5593  	run(t, testTransportResponseBodyWritableOnProtocolSwitch, []testMode{http1Mode})
  5594  }
  5595  func testTransportResponseBodyWritableOnProtocolSwitch(t *testing.T, mode testMode) {
  5596  	done := make(chan struct{})
  5597  	defer close(done)
  5598  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5599  		conn, _, err := w.(Hijacker).Hijack()
  5600  		if err != nil {
  5601  			t.Error(err)
  5602  			return
  5603  		}
  5604  		defer conn.Close()
  5605  		io.WriteString(conn, "HTTP/1.1 101 Switching Protocols Hi\r\nConnection: upgRADe\r\nUpgrade: foo\r\n\r\nSome buffered data\n")
  5606  		bs := bufio.NewScanner(conn)
  5607  		bs.Scan()
  5608  		fmt.Fprintf(conn, "%s\n", strings.ToUpper(bs.Text()))
  5609  		<-done
  5610  	}))
  5611  
  5612  	req, _ := NewRequest("GET", cst.ts.URL, nil)
  5613  	req.Header.Set("Upgrade", "foo")
  5614  	req.Header.Set("Connection", "upgrade")
  5615  	res, err := cst.c.Do(req)
  5616  	if err != nil {
  5617  		t.Fatal(err)
  5618  	}
  5619  	if res.StatusCode != 101 {
  5620  		t.Fatalf("expected 101 switching protocols; got %v, %v", res.Status, res.Header)
  5621  	}
  5622  	rwc, ok := res.Body.(io.ReadWriteCloser)
  5623  	if !ok {
  5624  		t.Fatalf("expected a ReadWriteCloser; got a %T", res.Body)
  5625  	}
  5626  	defer rwc.Close()
  5627  	bs := bufio.NewScanner(rwc)
  5628  	if !bs.Scan() {
  5629  		t.Fatalf("expected readable input")
  5630  	}
  5631  	if got, want := bs.Text(), "Some buffered data"; got != want {
  5632  		t.Errorf("read %q; want %q", got, want)
  5633  	}
  5634  	io.WriteString(rwc, "echo\n")
  5635  	if !bs.Scan() {
  5636  		t.Fatalf("expected another line")
  5637  	}
  5638  	if got, want := bs.Text(), "ECHO"; got != want {
  5639  		t.Errorf("read %q; want %q", got, want)
  5640  	}
  5641  }
  5642  
  5643  func TestTransportCONNECTBidi(t *testing.T) { run(t, testTransportCONNECTBidi, []testMode{http1Mode}) }
  5644  func testTransportCONNECTBidi(t *testing.T, mode testMode) {
  5645  	const target = "backend:443"
  5646  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5647  		if r.Method != "CONNECT" {
  5648  			t.Errorf("unexpected method %q", r.Method)
  5649  			w.WriteHeader(500)
  5650  			return
  5651  		}
  5652  		if r.RequestURI != target {
  5653  			t.Errorf("unexpected CONNECT target %q", r.RequestURI)
  5654  			w.WriteHeader(500)
  5655  			return
  5656  		}
  5657  		nc, brw, err := w.(Hijacker).Hijack()
  5658  		if err != nil {
  5659  			t.Error(err)
  5660  			return
  5661  		}
  5662  		defer nc.Close()
  5663  		nc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
  5664  		// Switch to a little protocol that capitalize its input lines:
  5665  		for {
  5666  			line, err := brw.ReadString('\n')
  5667  			if err != nil {
  5668  				if err != io.EOF {
  5669  					t.Error(err)
  5670  				}
  5671  				return
  5672  			}
  5673  			io.WriteString(brw, strings.ToUpper(line))
  5674  			brw.Flush()
  5675  		}
  5676  	}))
  5677  	pr, pw := io.Pipe()
  5678  	defer pw.Close()
  5679  	req, err := NewRequest("CONNECT", cst.ts.URL, pr)
  5680  	if err != nil {
  5681  		t.Fatal(err)
  5682  	}
  5683  	req.URL.Opaque = target
  5684  	res, err := cst.c.Do(req)
  5685  	if err != nil {
  5686  		t.Fatal(err)
  5687  	}
  5688  	defer res.Body.Close()
  5689  	if res.StatusCode != 200 {
  5690  		t.Fatalf("status code = %d; want 200", res.StatusCode)
  5691  	}
  5692  	br := bufio.NewReader(res.Body)
  5693  	for _, str := range []string{"foo", "bar", "baz"} {
  5694  		fmt.Fprintf(pw, "%s\n", str)
  5695  		got, err := br.ReadString('\n')
  5696  		if err != nil {
  5697  			t.Fatal(err)
  5698  		}
  5699  		got = strings.TrimSpace(got)
  5700  		want := strings.ToUpper(str)
  5701  		if got != want {
  5702  			t.Fatalf("got %q; want %q", got, want)
  5703  		}
  5704  	}
  5705  }
  5706  
  5707  func TestTransportRequestReplayable(t *testing.T) {
  5708  	someBody := io.NopCloser(strings.NewReader(""))
  5709  	tests := []struct {
  5710  		name string
  5711  		req  *Request
  5712  		want bool
  5713  	}{
  5714  		{
  5715  			name: "GET",
  5716  			req:  &Request{Method: "GET"},
  5717  			want: true,
  5718  		},
  5719  		{
  5720  			name: "GET_http.NoBody",
  5721  			req:  &Request{Method: "GET", Body: NoBody},
  5722  			want: true,
  5723  		},
  5724  		{
  5725  			name: "GET_body",
  5726  			req:  &Request{Method: "GET", Body: someBody},
  5727  			want: false,
  5728  		},
  5729  		{
  5730  			name: "POST",
  5731  			req:  &Request{Method: "POST"},
  5732  			want: false,
  5733  		},
  5734  		{
  5735  			name: "POST_idempotency-key",
  5736  			req:  &Request{Method: "POST", Header: Header{"Idempotency-Key": {"x"}}},
  5737  			want: true,
  5738  		},
  5739  		{
  5740  			name: "POST_x-idempotency-key",
  5741  			req:  &Request{Method: "POST", Header: Header{"X-Idempotency-Key": {"x"}}},
  5742  			want: true,
  5743  		},
  5744  		{
  5745  			name: "POST_body",
  5746  			req:  &Request{Method: "POST", Header: Header{"Idempotency-Key": {"x"}}, Body: someBody},
  5747  			want: false,
  5748  		},
  5749  	}
  5750  	for _, tt := range tests {
  5751  		t.Run(tt.name, func(t *testing.T) {
  5752  			got := tt.req.ExportIsReplayable()
  5753  			if got != tt.want {
  5754  				t.Errorf("replyable = %v; want %v", got, tt.want)
  5755  			}
  5756  		})
  5757  	}
  5758  }
  5759  
  5760  // testMockTCPConn is a mock TCP connection used to test that
  5761  // ReadFrom is called when sending the request body.
  5762  type testMockTCPConn struct {
  5763  	*net.TCPConn
  5764  
  5765  	ReadFromCalled bool
  5766  }
  5767  
  5768  func (c *testMockTCPConn) ReadFrom(r io.Reader) (int64, error) {
  5769  	c.ReadFromCalled = true
  5770  	return c.TCPConn.ReadFrom(r)
  5771  }
  5772  
  5773  func TestTransportRequestWriteRoundTrip(t *testing.T) { run(t, testTransportRequestWriteRoundTrip) }
  5774  func testTransportRequestWriteRoundTrip(t *testing.T, mode testMode) {
  5775  	nBytes := int64(1 << 10)
  5776  	newFileFunc := func() (r io.Reader, done func(), err error) {
  5777  		f, err := os.CreateTemp("", "net-http-newfilefunc")
  5778  		if err != nil {
  5779  			return nil, nil, err
  5780  		}
  5781  
  5782  		// Write some bytes to the file to enable reading.
  5783  		if _, err := io.CopyN(f, rand.Reader, nBytes); err != nil {
  5784  			return nil, nil, fmt.Errorf("failed to write data to file: %v", err)
  5785  		}
  5786  		if _, err := f.Seek(0, 0); err != nil {
  5787  			return nil, nil, fmt.Errorf("failed to seek to front: %v", err)
  5788  		}
  5789  
  5790  		done = func() {
  5791  			f.Close()
  5792  			os.Remove(f.Name())
  5793  		}
  5794  
  5795  		return f, done, nil
  5796  	}
  5797  
  5798  	newBufferFunc := func() (io.Reader, func(), error) {
  5799  		return bytes.NewBuffer(make([]byte, nBytes)), func() {}, nil
  5800  	}
  5801  
  5802  	cases := []struct {
  5803  		name             string
  5804  		readerFunc       func() (io.Reader, func(), error)
  5805  		contentLength    int64
  5806  		expectedReadFrom bool
  5807  	}{
  5808  		{
  5809  			name:             "file, length",
  5810  			readerFunc:       newFileFunc,
  5811  			contentLength:    nBytes,
  5812  			expectedReadFrom: true,
  5813  		},
  5814  		{
  5815  			name:       "file, no length",
  5816  			readerFunc: newFileFunc,
  5817  		},
  5818  		{
  5819  			name:          "file, negative length",
  5820  			readerFunc:    newFileFunc,
  5821  			contentLength: -1,
  5822  		},
  5823  		{
  5824  			name:          "buffer",
  5825  			contentLength: nBytes,
  5826  			readerFunc:    newBufferFunc,
  5827  		},
  5828  		{
  5829  			name:       "buffer, no length",
  5830  			readerFunc: newBufferFunc,
  5831  		},
  5832  		{
  5833  			name:          "buffer, length -1",
  5834  			contentLength: -1,
  5835  			readerFunc:    newBufferFunc,
  5836  		},
  5837  	}
  5838  
  5839  	for _, tc := range cases {
  5840  		t.Run(tc.name, func(t *testing.T) {
  5841  			r, cleanup, err := tc.readerFunc()
  5842  			if err != nil {
  5843  				t.Fatal(err)
  5844  			}
  5845  			defer cleanup()
  5846  
  5847  			tConn := &testMockTCPConn{}
  5848  			trFunc := func(tr *Transport) {
  5849  				tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
  5850  					var d net.Dialer
  5851  					conn, err := d.DialContext(ctx, network, addr)
  5852  					if err != nil {
  5853  						return nil, err
  5854  					}
  5855  
  5856  					tcpConn, ok := conn.(*net.TCPConn)
  5857  					if !ok {
  5858  						return nil, fmt.Errorf("%s/%s does not provide a *net.TCPConn", network, addr)
  5859  					}
  5860  
  5861  					tConn.TCPConn = tcpConn
  5862  					return tConn, nil
  5863  				}
  5864  			}
  5865  
  5866  			cst := newClientServerTest(
  5867  				t,
  5868  				mode,
  5869  				HandlerFunc(func(w ResponseWriter, r *Request) {
  5870  					io.Copy(io.Discard, r.Body)
  5871  					r.Body.Close()
  5872  					w.WriteHeader(200)
  5873  				}),
  5874  				trFunc,
  5875  			)
  5876  
  5877  			req, err := NewRequest("PUT", cst.ts.URL, r)
  5878  			if err != nil {
  5879  				t.Fatal(err)
  5880  			}
  5881  			req.ContentLength = tc.contentLength
  5882  			req.Header.Set("Content-Type", "application/octet-stream")
  5883  			resp, err := cst.c.Do(req)
  5884  			if err != nil {
  5885  				t.Fatal(err)
  5886  			}
  5887  			defer resp.Body.Close()
  5888  			if resp.StatusCode != 200 {
  5889  				t.Fatalf("status code = %d; want 200", resp.StatusCode)
  5890  			}
  5891  
  5892  			expectedReadFrom := tc.expectedReadFrom
  5893  			if mode != http1Mode {
  5894  				expectedReadFrom = false
  5895  			}
  5896  			if !tConn.ReadFromCalled && expectedReadFrom {
  5897  				t.Fatalf("did not call ReadFrom")
  5898  			}
  5899  
  5900  			if tConn.ReadFromCalled && !expectedReadFrom {
  5901  				t.Fatalf("ReadFrom was unexpectedly invoked")
  5902  			}
  5903  		})
  5904  	}
  5905  }
  5906  
  5907  func TestTransportClone(t *testing.T) {
  5908  	tr := &Transport{
  5909  		Proxy:                  func(*Request) (*url.URL, error) { panic("") },
  5910  		DialContext:            func(ctx context.Context, network, addr string) (net.Conn, error) { panic("") },
  5911  		Dial:                   func(network, addr string) (net.Conn, error) { panic("") },
  5912  		DialTLS:                func(network, addr string) (net.Conn, error) { panic("") },
  5913  		DialTLSContext:         func(ctx context.Context, network, addr string) (net.Conn, error) { panic("") },
  5914  		TLSClientConfig:        new(tls.Config),
  5915  		TLSHandshakeTimeout:    time.Second,
  5916  		DisableKeepAlives:      true,
  5917  		DisableCompression:     true,
  5918  		MaxIdleConns:           1,
  5919  		MaxIdleConnsPerHost:    1,
  5920  		MaxConnsPerHost:        1,
  5921  		IdleConnTimeout:        time.Second,
  5922  		ResponseHeaderTimeout:  time.Second,
  5923  		ExpectContinueTimeout:  time.Second,
  5924  		ProxyConnectHeader:     Header{},
  5925  		GetProxyConnectHeader:  func(context.Context, *url.URL, string) (Header, error) { return nil, nil },
  5926  		MaxResponseHeaderBytes: 1,
  5927  		ForceAttemptHTTP2:      true,
  5928  		TLSNextProto: map[string]func(authority string, c *tls.Conn) RoundTripper{
  5929  			"foo": func(authority string, c *tls.Conn) RoundTripper { panic("") },
  5930  		},
  5931  		ReadBufferSize:  1,
  5932  		WriteBufferSize: 1,
  5933  	}
  5934  	tr2 := tr.Clone()
  5935  	rv := reflect.ValueOf(tr2).Elem()
  5936  	rt := rv.Type()
  5937  	for i := 0; i < rt.NumField(); i++ {
  5938  		sf := rt.Field(i)
  5939  		if !token.IsExported(sf.Name) {
  5940  			continue
  5941  		}
  5942  		if rv.Field(i).IsZero() {
  5943  			t.Errorf("cloned field t2.%s is zero", sf.Name)
  5944  		}
  5945  	}
  5946  
  5947  	if _, ok := tr2.TLSNextProto["foo"]; !ok {
  5948  		t.Errorf("cloned Transport lacked TLSNextProto 'foo' key")
  5949  	}
  5950  
  5951  	// But test that a nil TLSNextProto is kept nil:
  5952  	tr = new(Transport)
  5953  	tr2 = tr.Clone()
  5954  	if tr2.TLSNextProto != nil {
  5955  		t.Errorf("Transport.TLSNextProto unexpected non-nil")
  5956  	}
  5957  }
  5958  
  5959  func TestIs408(t *testing.T) {
  5960  	tests := []struct {
  5961  		in   string
  5962  		want bool
  5963  	}{
  5964  		{"HTTP/1.0 408", true},
  5965  		{"HTTP/1.1 408", true},
  5966  		{"HTTP/1.8 408", true},
  5967  		{"HTTP/2.0 408", false}, // maybe h2c would do this? but false for now.
  5968  		{"HTTP/1.1 408 ", true},
  5969  		{"HTTP/1.1 40", false},
  5970  		{"http/1.0 408", false},
  5971  		{"HTTP/1-1 408", false},
  5972  	}
  5973  	for _, tt := range tests {
  5974  		if got := Export_is408Message([]byte(tt.in)); got != tt.want {
  5975  			t.Errorf("is408Message(%q) = %v; want %v", tt.in, got, tt.want)
  5976  		}
  5977  	}
  5978  }
  5979  
  5980  func TestTransportIgnores408(t *testing.T) {
  5981  	run(t, testTransportIgnores408, []testMode{http1Mode}, testNotParallel)
  5982  }
  5983  func testTransportIgnores408(t *testing.T, mode testMode) {
  5984  	// Not parallel. Relies on mutating the log package's global Output.
  5985  	defer log.SetOutput(log.Writer())
  5986  
  5987  	var logout strings.Builder
  5988  	log.SetOutput(&logout)
  5989  
  5990  	const target = "backend:443"
  5991  
  5992  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  5993  		nc, _, err := w.(Hijacker).Hijack()
  5994  		if err != nil {
  5995  			t.Error(err)
  5996  			return
  5997  		}
  5998  		defer nc.Close()
  5999  		nc.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok"))
  6000  		nc.Write([]byte("HTTP/1.1 408 bye\r\n")) // changing 408 to 409 makes test fail
  6001  	}))
  6002  	req, err := NewRequest("GET", cst.ts.URL, nil)
  6003  	if err != nil {
  6004  		t.Fatal(err)
  6005  	}
  6006  	res, err := cst.c.Do(req)
  6007  	if err != nil {
  6008  		t.Fatal(err)
  6009  	}
  6010  	slurp, err := io.ReadAll(res.Body)
  6011  	if err != nil {
  6012  		t.Fatal(err)
  6013  	}
  6014  	if err != nil {
  6015  		t.Fatal(err)
  6016  	}
  6017  	if string(slurp) != "ok" {
  6018  		t.Fatalf("got %q; want ok", slurp)
  6019  	}
  6020  
  6021  	t0 := time.Now()
  6022  	for i := 0; i < 50; i++ {
  6023  		time.Sleep(time.Duration(i) * 5 * time.Millisecond)
  6024  		if cst.tr.IdleConnKeyCountForTesting() == 0 {
  6025  			if got := logout.String(); got != "" {
  6026  				t.Fatalf("expected no log output; got: %s", got)
  6027  			}
  6028  			return
  6029  		}
  6030  	}
  6031  	t.Fatalf("timeout after %v waiting for Transport connections to die off", time.Since(t0))
  6032  }
  6033  
  6034  func TestInvalidHeaderResponse(t *testing.T) {
  6035  	run(t, testInvalidHeaderResponse, []testMode{http1Mode})
  6036  }
  6037  func testInvalidHeaderResponse(t *testing.T, mode testMode) {
  6038  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  6039  		conn, buf, _ := w.(Hijacker).Hijack()
  6040  		buf.Write([]byte("HTTP/1.1 200 OK\r\n" +
  6041  			"Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" +
  6042  			"Content-Type: text/html; charset=utf-8\r\n" +
  6043  			"Content-Length: 0\r\n" +
  6044  			"Foo : bar\r\n\r\n"))
  6045  		buf.Flush()
  6046  		conn.Close()
  6047  	}))
  6048  	res, err := cst.c.Get(cst.ts.URL)
  6049  	if err != nil {
  6050  		t.Fatal(err)
  6051  	}
  6052  	defer res.Body.Close()
  6053  	if v := res.Header.Get("Foo"); v != "" {
  6054  		t.Errorf(`unexpected "Foo" header: %q`, v)
  6055  	}
  6056  	if v := res.Header.Get("Foo "); v != "bar" {
  6057  		t.Errorf(`bad "Foo " header value: %q, want %q`, v, "bar")
  6058  	}
  6059  }
  6060  
  6061  type bodyCloser bool
  6062  
  6063  func (bc *bodyCloser) Close() error {
  6064  	*bc = true
  6065  	return nil
  6066  }
  6067  func (bc *bodyCloser) Read(b []byte) (n int, err error) {
  6068  	return 0, io.EOF
  6069  }
  6070  
  6071  // Issue 35015: ensure that Transport closes the body on any error
  6072  // with an invalid request, as promised by Client.Do docs.
  6073  func TestTransportClosesBodyOnInvalidRequests(t *testing.T) {
  6074  	run(t, testTransportClosesBodyOnInvalidRequests)
  6075  }
  6076  func testTransportClosesBodyOnInvalidRequests(t *testing.T, mode testMode) {
  6077  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  6078  		t.Errorf("Should not have been invoked")
  6079  	})).ts
  6080  
  6081  	u, _ := url.Parse(cst.URL)
  6082  
  6083  	tests := []struct {
  6084  		name    string
  6085  		req     *Request
  6086  		wantErr string
  6087  	}{
  6088  		{
  6089  			name: "invalid method",
  6090  			req: &Request{
  6091  				Method: " ",
  6092  				URL:    u,
  6093  			},
  6094  			wantErr: `invalid method " "`,
  6095  		},
  6096  		{
  6097  			name: "nil URL",
  6098  			req: &Request{
  6099  				Method: "GET",
  6100  			},
  6101  			wantErr: `nil Request.URL`,
  6102  		},
  6103  		{
  6104  			name: "invalid header key",
  6105  			req: &Request{
  6106  				Method: "GET",
  6107  				Header: Header{"💡": {"emoji"}},
  6108  				URL:    u,
  6109  			},
  6110  			wantErr: `invalid header field name "💡"`,
  6111  		},
  6112  		{
  6113  			name: "invalid header value",
  6114  			req: &Request{
  6115  				Method: "POST",
  6116  				Header: Header{"key": {"\x19"}},
  6117  				URL:    u,
  6118  			},
  6119  			wantErr: `invalid header field value for "key"`,
  6120  		},
  6121  		{
  6122  			name: "non HTTP(s) scheme",
  6123  			req: &Request{
  6124  				Method: "POST",
  6125  				URL:    &url.URL{Scheme: "faux"},
  6126  			},
  6127  			wantErr: `unsupported protocol scheme "faux"`,
  6128  		},
  6129  		{
  6130  			name: "no Host in URL",
  6131  			req: &Request{
  6132  				Method: "POST",
  6133  				URL:    &url.URL{Scheme: "http"},
  6134  			},
  6135  			wantErr: `no Host in request URL`,
  6136  		},
  6137  	}
  6138  
  6139  	for _, tt := range tests {
  6140  		t.Run(tt.name, func(t *testing.T) {
  6141  			var bc bodyCloser
  6142  			req := tt.req
  6143  			req.Body = &bc
  6144  			_, err := cst.Client().Do(tt.req)
  6145  			if err == nil {
  6146  				t.Fatal("Expected an error")
  6147  			}
  6148  			if !bc {
  6149  				t.Fatal("Expected body to have been closed")
  6150  			}
  6151  			if g, w := err.Error(), tt.wantErr; !strings.HasSuffix(g, w) {
  6152  				t.Fatalf("Error mismatch: %q does not end with %q", g, w)
  6153  			}
  6154  		})
  6155  	}
  6156  }
  6157  
  6158  // breakableConn is a net.Conn wrapper with a Write method
  6159  // that will fail when its brokenState is true.
  6160  type breakableConn struct {
  6161  	net.Conn
  6162  	*brokenState
  6163  }
  6164  
  6165  type brokenState struct {
  6166  	sync.Mutex
  6167  	broken bool
  6168  }
  6169  
  6170  func (w *breakableConn) Write(b []byte) (n int, err error) {
  6171  	w.Lock()
  6172  	defer w.Unlock()
  6173  	if w.broken {
  6174  		return 0, errors.New("some write error")
  6175  	}
  6176  	return w.Conn.Write(b)
  6177  }
  6178  
  6179  // Issue 34978: don't cache a broken HTTP/2 connection
  6180  func TestDontCacheBrokenHTTP2Conn(t *testing.T) {
  6181  	run(t, testDontCacheBrokenHTTP2Conn, []testMode{http2Mode})
  6182  }
  6183  func testDontCacheBrokenHTTP2Conn(t *testing.T, mode testMode) {
  6184  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), optQuietLog)
  6185  
  6186  	var brokenState brokenState
  6187  
  6188  	const numReqs = 5
  6189  	var numDials, gotConns uint32 // atomic
  6190  
  6191  	cst.tr.Dial = func(netw, addr string) (net.Conn, error) {
  6192  		atomic.AddUint32(&numDials, 1)
  6193  		c, err := net.Dial(netw, addr)
  6194  		if err != nil {
  6195  			t.Errorf("unexpected Dial error: %v", err)
  6196  			return nil, err
  6197  		}
  6198  		return &breakableConn{c, &brokenState}, err
  6199  	}
  6200  
  6201  	for i := 1; i <= numReqs; i++ {
  6202  		brokenState.Lock()
  6203  		brokenState.broken = false
  6204  		brokenState.Unlock()
  6205  
  6206  		// doBreak controls whether we break the TCP connection after the TLS
  6207  		// handshake (before the HTTP/2 handshake). We test a few failures
  6208  		// in a row followed by a final success.
  6209  		doBreak := i != numReqs
  6210  
  6211  		ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
  6212  			GotConn: func(info httptrace.GotConnInfo) {
  6213  				t.Logf("got conn: %v, reused=%v, wasIdle=%v, idleTime=%v", info.Conn.LocalAddr(), info.Reused, info.WasIdle, info.IdleTime)
  6214  				atomic.AddUint32(&gotConns, 1)
  6215  			},
  6216  			TLSHandshakeDone: func(cfg tls.ConnectionState, err error) {
  6217  				brokenState.Lock()
  6218  				defer brokenState.Unlock()
  6219  				if doBreak {
  6220  					brokenState.broken = true
  6221  				}
  6222  			},
  6223  		})
  6224  		req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil)
  6225  		if err != nil {
  6226  			t.Fatal(err)
  6227  		}
  6228  		_, err = cst.c.Do(req)
  6229  		if doBreak != (err != nil) {
  6230  			t.Errorf("for iteration %d, doBreak=%v; unexpected error %v", i, doBreak, err)
  6231  		}
  6232  	}
  6233  	if got, want := atomic.LoadUint32(&gotConns), 1; int(got) != want {
  6234  		t.Errorf("GotConn calls = %v; want %v", got, want)
  6235  	}
  6236  	if got, want := atomic.LoadUint32(&numDials), numReqs; int(got) != want {
  6237  		t.Errorf("Dials = %v; want %v", got, want)
  6238  	}
  6239  }
  6240  
  6241  // Issue 34941
  6242  // When the client has too many concurrent requests on a single connection,
  6243  // http.http2noCachedConnError is reported on multiple requests. There should
  6244  // only be one decrement regardless of the number of failures.
  6245  func TestTransportDecrementConnWhenIdleConnRemoved(t *testing.T) {
  6246  	run(t, testTransportDecrementConnWhenIdleConnRemoved, []testMode{http2Mode})
  6247  }
  6248  func testTransportDecrementConnWhenIdleConnRemoved(t *testing.T, mode testMode) {
  6249  	CondSkipHTTP2(t)
  6250  
  6251  	h := HandlerFunc(func(w ResponseWriter, r *Request) {
  6252  		_, err := w.Write([]byte("foo"))
  6253  		if err != nil {
  6254  			t.Fatalf("Write: %v", err)
  6255  		}
  6256  	})
  6257  
  6258  	ts := newClientServerTest(t, mode, h).ts
  6259  
  6260  	c := ts.Client()
  6261  	tr := c.Transport.(*Transport)
  6262  	tr.MaxConnsPerHost = 1
  6263  
  6264  	errCh := make(chan error, 300)
  6265  	doReq := func() {
  6266  		resp, err := c.Get(ts.URL)
  6267  		if err != nil {
  6268  			errCh <- fmt.Errorf("request failed: %v", err)
  6269  			return
  6270  		}
  6271  		defer resp.Body.Close()
  6272  		_, err = io.ReadAll(resp.Body)
  6273  		if err != nil {
  6274  			errCh <- fmt.Errorf("read body failed: %v", err)
  6275  		}
  6276  	}
  6277  
  6278  	var wg sync.WaitGroup
  6279  	for i := 0; i < 300; i++ {
  6280  		wg.Add(1)
  6281  		go func() {
  6282  			defer wg.Done()
  6283  			doReq()
  6284  		}()
  6285  	}
  6286  	wg.Wait()
  6287  	close(errCh)
  6288  
  6289  	for err := range errCh {
  6290  		t.Errorf("error occurred: %v", err)
  6291  	}
  6292  }
  6293  
  6294  // Issue 36820
  6295  // Test that we use the older backward compatible cancellation protocol
  6296  // when a RoundTripper is registered via RegisterProtocol.
  6297  func TestAltProtoCancellation(t *testing.T) {
  6298  	defer afterTest(t)
  6299  	tr := &Transport{}
  6300  	c := &Client{
  6301  		Transport: tr,
  6302  		Timeout:   time.Millisecond,
  6303  	}
  6304  	tr.RegisterProtocol("timeout", timeoutProto{})
  6305  	_, err := c.Get("timeout://bar.com/path")
  6306  	if err == nil {
  6307  		t.Error("request unexpectedly succeeded")
  6308  	} else if !strings.Contains(err.Error(), timeoutProtoErr.Error()) {
  6309  		t.Errorf("got error %q, does not contain expected string %q", err, timeoutProtoErr)
  6310  	}
  6311  }
  6312  
  6313  var timeoutProtoErr = errors.New("canceled as expected")
  6314  
  6315  type timeoutProto struct{}
  6316  
  6317  func (timeoutProto) RoundTrip(req *Request) (*Response, error) {
  6318  	select {
  6319  	case <-req.Cancel:
  6320  		return nil, timeoutProtoErr
  6321  	case <-time.After(5 * time.Second):
  6322  		return nil, errors.New("request was not canceled")
  6323  	}
  6324  }
  6325  
  6326  type roundTripFunc func(r *Request) (*Response, error)
  6327  
  6328  func (f roundTripFunc) RoundTrip(r *Request) (*Response, error) { return f(r) }
  6329  
  6330  // Issue 32441: body is not reset after ErrSkipAltProtocol
  6331  func TestIssue32441(t *testing.T) { run(t, testIssue32441, []testMode{http1Mode}) }
  6332  func testIssue32441(t *testing.T, mode testMode) {
  6333  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  6334  		if n, _ := io.Copy(io.Discard, r.Body); n == 0 {
  6335  			t.Error("body length is zero")
  6336  		}
  6337  	})).ts
  6338  	c := ts.Client()
  6339  	c.Transport.(*Transport).RegisterProtocol("http", roundTripFunc(func(r *Request) (*Response, error) {
  6340  		// Draining body to trigger failure condition on actual request to server.
  6341  		if n, _ := io.Copy(io.Discard, r.Body); n == 0 {
  6342  			t.Error("body length is zero during round trip")
  6343  		}
  6344  		return nil, ErrSkipAltProtocol
  6345  	}))
  6346  	if _, err := c.Post(ts.URL, "application/octet-stream", bytes.NewBufferString("data")); err != nil {
  6347  		t.Error(err)
  6348  	}
  6349  }
  6350  
  6351  // Issue 39017. Ensure that HTTP/1 transports reject Content-Length headers
  6352  // that contain a sign (eg. "+3"), per RFC 2616, Section 14.13.
  6353  func TestTransportRejectsSignInContentLength(t *testing.T) {
  6354  	run(t, testTransportRejectsSignInContentLength, []testMode{http1Mode})
  6355  }
  6356  func testTransportRejectsSignInContentLength(t *testing.T, mode testMode) {
  6357  	cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
  6358  		w.Header().Set("Content-Length", "+3")
  6359  		w.Write([]byte("abc"))
  6360  	})).ts
  6361  
  6362  	c := cst.Client()
  6363  	res, err := c.Get(cst.URL)
  6364  	if err == nil || res != nil {
  6365  		t.Fatal("Expected a non-nil error and a nil http.Response")
  6366  	}
  6367  	if got, want := err.Error(), `bad Content-Length "+3"`; !strings.Contains(got, want) {
  6368  		t.Fatalf("Error mismatch\nGot: %q\nWanted substring: %q", got, want)
  6369  	}
  6370  }
  6371  
  6372  // dumpConn is a net.Conn which writes to Writer and reads from Reader
  6373  type dumpConn struct {
  6374  	io.Writer
  6375  	io.Reader
  6376  }
  6377  
  6378  func (c *dumpConn) Close() error                       { return nil }
  6379  func (c *dumpConn) LocalAddr() net.Addr                { return nil }
  6380  func (c *dumpConn) RemoteAddr() net.Addr               { return nil }
  6381  func (c *dumpConn) SetDeadline(t time.Time) error      { return nil }
  6382  func (c *dumpConn) SetReadDeadline(t time.Time) error  { return nil }
  6383  func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
  6384  
  6385  // delegateReader is a reader that delegates to another reader,
  6386  // once it arrives on a channel.
  6387  type delegateReader struct {
  6388  	c chan io.Reader
  6389  	r io.Reader // nil until received from c
  6390  }
  6391  
  6392  func (r *delegateReader) Read(p []byte) (int, error) {
  6393  	if r.r == nil {
  6394  		var ok bool
  6395  		if r.r, ok = <-r.c; !ok {
  6396  			return 0, errors.New("delegate closed")
  6397  		}
  6398  	}
  6399  	return r.r.Read(p)
  6400  }
  6401  
  6402  func testTransportRace(req *Request) {
  6403  	save := req.Body
  6404  	pr, pw := io.Pipe()
  6405  	defer pr.Close()
  6406  	defer pw.Close()
  6407  	dr := &delegateReader{c: make(chan io.Reader)}
  6408  
  6409  	t := &Transport{
  6410  		Dial: func(net, addr string) (net.Conn, error) {
  6411  			return &dumpConn{pw, dr}, nil
  6412  		},
  6413  	}
  6414  	defer t.CloseIdleConnections()
  6415  
  6416  	quitReadCh := make(chan struct{})
  6417  	// Wait for the request before replying with a dummy response:
  6418  	go func() {
  6419  		defer close(quitReadCh)
  6420  
  6421  		req, err := ReadRequest(bufio.NewReader(pr))
  6422  		if err == nil {
  6423  			// Ensure all the body is read; otherwise
  6424  			// we'll get a partial dump.
  6425  			io.Copy(io.Discard, req.Body)
  6426  			req.Body.Close()
  6427  		}
  6428  		select {
  6429  		case dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n"):
  6430  		case quitReadCh <- struct{}{}:
  6431  			// Ensure delegate is closed so Read doesn't block forever.
  6432  			close(dr.c)
  6433  		}
  6434  	}()
  6435  
  6436  	t.RoundTrip(req)
  6437  
  6438  	// Ensure the reader returns before we reset req.Body to prevent
  6439  	// a data race on req.Body.
  6440  	pw.Close()
  6441  	<-quitReadCh
  6442  
  6443  	req.Body = save
  6444  }
  6445  
  6446  // Issue 37669
  6447  // Test that a cancellation doesn't result in a data race due to the writeLoop
  6448  // goroutine being left running, if the caller mutates the processed Request
  6449  // upon completion.
  6450  func TestErrorWriteLoopRace(t *testing.T) {
  6451  	if testing.Short() {
  6452  		return
  6453  	}
  6454  	t.Parallel()
  6455  	for i := 0; i < 1000; i++ {
  6456  		delay := time.Duration(mrand.Intn(5)) * time.Millisecond
  6457  		ctx, cancel := context.WithTimeout(context.Background(), delay)
  6458  		defer cancel()
  6459  
  6460  		r := bytes.NewBuffer(make([]byte, 10000))
  6461  		req, err := NewRequestWithContext(ctx, MethodPost, "http://example.com", r)
  6462  		if err != nil {
  6463  			t.Fatal(err)
  6464  		}
  6465  
  6466  		testTransportRace(req)
  6467  	}
  6468  }
  6469  
  6470  // Issue 41600
  6471  // Test that a new request which uses the connection of an active request
  6472  // cannot cause it to be canceled as well.
  6473  func TestCancelRequestWhenSharingConnection(t *testing.T) {
  6474  	run(t, testCancelRequestWhenSharingConnection, []testMode{http1Mode})
  6475  }
  6476  func testCancelRequestWhenSharingConnection(t *testing.T, mode testMode) {
  6477  	reqc := make(chan chan struct{}, 2)
  6478  	ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, req *Request) {
  6479  		ch := make(chan struct{}, 1)
  6480  		reqc <- ch
  6481  		<-ch
  6482  		w.Header().Add("Content-Length", "0")
  6483  	})).ts
  6484  
  6485  	client := ts.Client()
  6486  	transport := client.Transport.(*Transport)
  6487  	transport.MaxIdleConns = 1
  6488  	transport.MaxConnsPerHost = 1
  6489  
  6490  	var wg sync.WaitGroup
  6491  
  6492  	wg.Add(1)
  6493  	putidlec := make(chan chan struct{})
  6494  	go func() {
  6495  		defer wg.Done()
  6496  		ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
  6497  			PutIdleConn: func(error) {
  6498  				// Signal that the idle conn has been returned to the pool,
  6499  				// and wait for the order to proceed.
  6500  				ch := make(chan struct{})
  6501  				putidlec <- ch
  6502  				<-ch
  6503  			},
  6504  		})
  6505  		req, _ := NewRequestWithContext(ctx, "GET", ts.URL, nil)
  6506  		res, err := client.Do(req)
  6507  		if err == nil {
  6508  			res.Body.Close()
  6509  		}
  6510  		if err != nil {
  6511  			t.Errorf("request 1: got err %v, want nil", err)
  6512  		}
  6513  	}()
  6514  
  6515  	// Wait for the first request to receive a response and return the
  6516  	// connection to the idle pool.
  6517  	r1c := <-reqc
  6518  	close(r1c)
  6519  	idlec := <-putidlec
  6520  
  6521  	wg.Add(1)
  6522  	cancelctx, cancel := context.WithCancel(context.Background())
  6523  	go func() {
  6524  		defer wg.Done()
  6525  		req, _ := NewRequestWithContext(cancelctx, "GET", ts.URL, nil)
  6526  		res, err := client.Do(req)
  6527  		if err == nil {
  6528  			res.Body.Close()
  6529  		}
  6530  		if !errors.Is(err, context.Canceled) {
  6531  			t.Errorf("request 2: got err %v, want Canceled", err)
  6532  		}
  6533  	}()
  6534  
  6535  	// Wait for the second request to arrive at the server, and then cancel
  6536  	// the request context.
  6537  	r2c := <-reqc
  6538  	cancel()
  6539  
  6540  	// Give the cancellation a moment to take effect, and then unblock the first request.
  6541  	time.Sleep(1 * time.Millisecond)
  6542  	close(idlec)
  6543  
  6544  	close(r2c)
  6545  	wg.Wait()
  6546  }
  6547  
  6548  func TestHandlerAbortRacesBodyRead(t *testing.T) { run(t, testHandlerAbortRacesBodyRead) }
  6549  func testHandlerAbortRacesBodyRead(t *testing.T, mode testMode) {
  6550  	ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
  6551  		go io.Copy(io.Discard, req.Body)
  6552  		panic(ErrAbortHandler)
  6553  	})).ts
  6554  
  6555  	var wg sync.WaitGroup
  6556  	for i := 0; i < 2; i++ {
  6557  		wg.Add(1)
  6558  		go func() {
  6559  			defer wg.Done()
  6560  			for j := 0; j < 10; j++ {
  6561  				const reqLen = 6 * 1024 * 1024
  6562  				req, _ := NewRequest("POST", ts.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
  6563  				req.ContentLength = reqLen
  6564  				resp, _ := ts.Client().Transport.RoundTrip(req)
  6565  				if resp != nil {
  6566  					resp.Body.Close()
  6567  				}
  6568  			}
  6569  		}()
  6570  	}
  6571  	wg.Wait()
  6572  }