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