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