Source file src/net/http/transport_test.go

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

View as plain text