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