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