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