gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/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/zhaochuninhefei/gmgo/gmhttp" 40 "gitee.com/zhaochuninhefei/gmgo/gmhttp/httptest" 41 "gitee.com/zhaochuninhefei/gmgo/gmhttp/httptrace" 42 "gitee.com/zhaochuninhefei/gmgo/gmhttp/httputil" 43 "gitee.com/zhaochuninhefei/gmgo/gmhttp/internal/testcert" 44 tls "gitee.com/zhaochuninhefei/gmgo/gmtls" 45 "gitee.com/zhaochuninhefei/gmgo/internal/nettrace" 46 "gitee.com/zhaochuninhefei/gmgo/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/": gitee.com/zhaochuninhefei/gmgo/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 // This automatically prevents an infinite resend loop because we'll run out of 3496 // the cached keep-alive connections eventually. 3497 func TestRetryRequestsOnError(t *testing.T) { 3498 newRequest := func(method, urlStr string, body io.Reader) *Request { 3499 req, err := NewRequest(method, urlStr, body) 3500 if err != nil { 3501 t.Fatal(err) 3502 } 3503 return req 3504 } 3505 3506 testCases := []struct { 3507 name string 3508 failureN int 3509 failureErr error 3510 // Note that we can't just re-use the Request object across calls to c.Do 3511 // because we need to rewind Body between calls. (GetBody is only used to 3512 // rewind Body on failure and redirects, not just because it's done.) 3513 req func() *Request 3514 reqString string 3515 }{ 3516 { 3517 name: "IdempotentNoBodySomeWritten", 3518 // Believe that we've written some bytes to the server, so we know we're 3519 // not just in the "retry when no bytes sent" case". 3520 failureN: 1, 3521 // Use the specific error that shouldRetryRequest looks for with idempotent requests. 3522 failureErr: ExportErrServerClosedIdle, 3523 req: func() *Request { 3524 return newRequest("GET", "http://fake.golang", nil) 3525 }, 3526 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`, 3527 }, 3528 { 3529 name: "IdempotentGetBodySomeWritten", 3530 // Believe that we've written some bytes to the server, so we know we're 3531 // not just in the "retry when no bytes sent" case". 3532 failureN: 1, 3533 // Use the specific error that shouldRetryRequest looks for with idempotent requests. 3534 failureErr: ExportErrServerClosedIdle, 3535 req: func() *Request { 3536 return newRequest("GET", "http://fake.golang", strings.NewReader("foo\n")) 3537 }, 3538 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`, 3539 }, 3540 { 3541 name: "NothingWrittenNoBody", 3542 // It's key that we return 0 here -- that's what enables Transport to know 3543 // that nothing was written, even though this is a non-idempotent request. 3544 failureN: 0, 3545 failureErr: errors.New("second write fails"), 3546 req: func() *Request { 3547 return newRequest("DELETE", "http://fake.golang", nil) 3548 }, 3549 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`, 3550 }, 3551 { 3552 name: "NothingWrittenGetBody", 3553 // It's key that we return 0 here -- that's what enables Transport to know 3554 // that nothing was written, even though this is a non-idempotent request. 3555 failureN: 0, 3556 failureErr: errors.New("second write fails"), 3557 // Note that NewRequest will set up GetBody for strings.Reader, which is 3558 // required for the retry to occur 3559 req: func() *Request { 3560 return newRequest("POST", "http://fake.golang", strings.NewReader("foo\n")) 3561 }, 3562 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`, 3563 }, 3564 } 3565 3566 for _, tc := range testCases { 3567 t.Run(tc.name, func(t *testing.T) { 3568 defer afterTest(t) 3569 3570 var ( 3571 mu sync.Mutex 3572 logbuf bytes.Buffer 3573 ) 3574 logf := func(format string, args ...interface{}) { 3575 mu.Lock() 3576 defer mu.Unlock() 3577 _, _ = fmt.Fprintf(&logbuf, format, args...) 3578 logbuf.WriteByte('\n') 3579 } 3580 3581 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3582 logf("Handler") 3583 w.Header().Set("X-Status", "ok") 3584 })) 3585 defer ts.Close() 3586 3587 var writeNumAtomic int32 3588 c := ts.Client() 3589 c.Transport.(*Transport).Dial = func(network, addr string) (net.Conn, error) { 3590 logf("Dial") 3591 c, err := net.Dial(network, ts.Listener.Addr().String()) 3592 if err != nil { 3593 logf("Dial error: %v", err) 3594 return nil, err 3595 } 3596 return &writerFuncConn{ 3597 Conn: c, 3598 write: func(p []byte) (n int, err error) { 3599 if atomic.AddInt32(&writeNumAtomic, 1) == 2 { 3600 logf("intentional write failure") 3601 return tc.failureN, tc.failureErr 3602 } 3603 logf("Write(%q)", p) 3604 return c.Write(p) 3605 }, 3606 }, nil 3607 } 3608 3609 SetRoundTripRetried(func() { 3610 logf("Retried.") 3611 }) 3612 defer SetRoundTripRetried(nil) 3613 3614 for i := 0; i < 3; i++ { 3615 t0 := time.Now() 3616 req := tc.req() 3617 res, err := c.Do(req) 3618 if err != nil { 3619 if time.Since(t0) < MaxWriteWaitBeforeConnReuse/2 { 3620 mu.Lock() 3621 got := logbuf.String() 3622 mu.Unlock() 3623 t.Fatalf("i=%d: Do = %v; log:\n%s", i, err, got) 3624 } 3625 t.Skipf("connection likely wasn't recycled within %d, interfering with actual test; skipping", MaxWriteWaitBeforeConnReuse) 3626 } 3627 _ = res.Body.Close() 3628 if res.Request != req { 3629 t.Errorf("Response.Request != original request; want identical Request") 3630 } 3631 } 3632 3633 mu.Lock() 3634 got := logbuf.String() 3635 mu.Unlock() 3636 want := fmt.Sprintf(`Dial 3637 Write("%s") 3638 Handler 3639 intentional write failure 3640 Retried. 3641 Dial 3642 Write("%s") 3643 Handler 3644 Write("%s") 3645 Handler 3646 `, tc.reqString, tc.reqString, tc.reqString) 3647 if got != want { 3648 t.Errorf("Log of events differs. Got:\n%s\nWant:\n%s", got, want) 3649 } 3650 }) 3651 } 3652 } 3653 3654 // Issue 6981 3655 func TestTransportClosesBodyOnError(t *testing.T) { 3656 setParallel(t) 3657 defer afterTest(t) 3658 readBody := make(chan error, 1) 3659 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3660 _, err := io.ReadAll(r.Body) 3661 readBody <- err 3662 })) 3663 defer ts.Close() 3664 c := ts.Client() 3665 fakeErr := errors.New("fake error") 3666 didClose := make(chan bool, 1) 3667 req, _ := NewRequest("POST", ts.URL, struct { 3668 io.Reader 3669 io.Closer 3670 }{ 3671 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), iotest.ErrReader(fakeErr)), 3672 closerFunc(func() error { 3673 select { 3674 case didClose <- true: 3675 default: 3676 } 3677 return nil 3678 }), 3679 }) 3680 res, err := c.Do(req) 3681 if res != nil { 3682 defer func(Body io.ReadCloser) { 3683 _ = Body.Close() 3684 }(res.Body) 3685 } 3686 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 3687 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 3688 } 3689 select { 3690 case err := <-readBody: 3691 if err == nil { 3692 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 3693 } 3694 case <-time.After(5 * time.Second): 3695 t.Error("timeout waiting for server handler to complete") 3696 } 3697 select { 3698 case <-didClose: 3699 default: 3700 t.Errorf("didn't see Body.Close") 3701 } 3702 } 3703 3704 func TestTransportDialTLS(t *testing.T) { 3705 setParallel(t) 3706 defer afterTest(t) 3707 var mu sync.Mutex // guards following 3708 var gotReq, didDial bool 3709 3710 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3711 mu.Lock() 3712 gotReq = true 3713 mu.Unlock() 3714 })) 3715 defer ts.Close() 3716 c := ts.Client() 3717 c.Transport.(*Transport).DialTLS = func(netw, addr string) (net.Conn, error) { 3718 mu.Lock() 3719 didDial = true 3720 mu.Unlock() 3721 c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig) 3722 if err != nil { 3723 return nil, err 3724 } 3725 return c, c.Handshake() 3726 } 3727 3728 res, err := c.Get(ts.URL) 3729 if err != nil { 3730 t.Fatal(err) 3731 } 3732 _ = res.Body.Close() 3733 mu.Lock() 3734 if !gotReq { 3735 t.Error("didn't get request") 3736 } 3737 if !didDial { 3738 t.Error("didn't use dial hook") 3739 } 3740 } 3741 3742 func TestTransportDialContext(t *testing.T) { 3743 setParallel(t) 3744 defer afterTest(t) 3745 var mu sync.Mutex // guards following 3746 var gotReq bool 3747 var receivedContext context.Context 3748 3749 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3750 mu.Lock() 3751 gotReq = true 3752 mu.Unlock() 3753 })) 3754 defer ts.Close() 3755 c := ts.Client() 3756 c.Transport.(*Transport).DialContext = func(ctx context.Context, netw, addr string) (net.Conn, error) { 3757 mu.Lock() 3758 receivedContext = ctx 3759 mu.Unlock() 3760 return net.Dial(netw, addr) 3761 } 3762 3763 req, err := NewRequest("GET", ts.URL, nil) 3764 if err != nil { 3765 t.Fatal(err) 3766 } 3767 ctx := context.WithValue(context.Background(), "some-key", "some-value") 3768 res, err := c.Do(req.WithContext(ctx)) 3769 if err != nil { 3770 t.Fatal(err) 3771 } 3772 _ = res.Body.Close() 3773 mu.Lock() 3774 if !gotReq { 3775 t.Error("didn't get request") 3776 } 3777 if receivedContext != ctx { 3778 t.Error("didn't receive correct context") 3779 } 3780 } 3781 3782 func TestTransportDialTLSContext(t *testing.T) { 3783 setParallel(t) 3784 defer afterTest(t) 3785 var mu sync.Mutex // guards following 3786 var gotReq bool 3787 var receivedContext context.Context 3788 3789 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3790 mu.Lock() 3791 gotReq = true 3792 mu.Unlock() 3793 })) 3794 defer ts.Close() 3795 c := ts.Client() 3796 c.Transport.(*Transport).DialTLSContext = func(ctx context.Context, netw, addr string) (net.Conn, error) { 3797 mu.Lock() 3798 receivedContext = ctx 3799 mu.Unlock() 3800 c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig) 3801 if err != nil { 3802 return nil, err 3803 } 3804 return c, c.HandshakeContext(ctx) 3805 } 3806 3807 req, err := NewRequest("GET", ts.URL, nil) 3808 if err != nil { 3809 t.Fatal(err) 3810 } 3811 ctx := context.WithValue(context.Background(), "some-key", "some-value") 3812 res, err := c.Do(req.WithContext(ctx)) 3813 if err != nil { 3814 t.Fatal(err) 3815 } 3816 _ = res.Body.Close() 3817 mu.Lock() 3818 if !gotReq { 3819 t.Error("didn't get request") 3820 } 3821 if receivedContext != ctx { 3822 t.Error("didn't receive correct context") 3823 } 3824 } 3825 3826 // Test for issue 8755 3827 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 3828 func TestRoundTripReturnsProxyError(t *testing.T) { 3829 badProxy := func(*Request) (*url.URL, error) { 3830 return nil, errors.New("errorMessage") 3831 } 3832 3833 tr := &Transport{Proxy: badProxy} 3834 3835 //goland:noinspection HttpUrlsUsage 3836 req, _ := NewRequest("GET", "http://example.com", nil) 3837 3838 _, err := tr.RoundTrip(req) 3839 3840 if err == nil { 3841 t.Error("Expected proxy error to be returned by RoundTrip") 3842 } 3843 } 3844 3845 // tests that putting an idle conn after a call to CloseIdleConns does return it 3846 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 3847 tr := &Transport{} 3848 wantIdle := func(when string, n int) bool { 3849 got := tr.IdleConnCountForTesting("http", "example.com") // key used by PutIdleTestConn 3850 if got == n { 3851 return true 3852 } 3853 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 3854 return false 3855 } 3856 wantIdle("start", 0) 3857 if !tr.PutIdleTestConn("http", "example.com") { 3858 t.Fatal("put failed") 3859 } 3860 if !tr.PutIdleTestConn("http", "example.com") { 3861 t.Fatal("second put failed") 3862 } 3863 wantIdle("after put", 2) 3864 tr.CloseIdleConnections() 3865 if !tr.IsIdleForTesting() { 3866 t.Error("should be idle after CloseIdleConnections") 3867 } 3868 wantIdle("after close idle", 0) 3869 if tr.PutIdleTestConn("http", "example.com") { 3870 t.Fatal("put didn't fail") 3871 } 3872 wantIdle("after second put", 0) 3873 3874 tr.QueueForIdleConnForTesting() // should toggle the transport out of idle mode 3875 if tr.IsIdleForTesting() { 3876 t.Error("shouldn't be idle after QueueForIdleConnForTesting") 3877 } 3878 if !tr.PutIdleTestConn("http", "example.com") { 3879 t.Fatal("after re-activation") 3880 } 3881 wantIdle("after final put", 1) 3882 } 3883 3884 // Test for issue 34282 3885 // Ensure that getConn doesn't call the GotConn trace hook on a HTTP/2 idle conn 3886 func TestTransportTraceGotConnH2IdleConns(t *testing.T) { 3887 tr := &Transport{} 3888 wantIdle := func(when string, n int) bool { 3889 got := tr.IdleConnCountForTesting("https", "example.com:443") // key used by PutIdleTestConnH2 3890 if got == n { 3891 return true 3892 } 3893 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 3894 return false 3895 } 3896 wantIdle("start", 0) 3897 alt := funcRoundTripper(func() {}) 3898 if !tr.PutIdleTestConnH2("https", "example.com:443", alt) { 3899 t.Fatal("put failed") 3900 } 3901 wantIdle("after put", 1) 3902 ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 3903 GotConn: func(httptrace.GotConnInfo) { 3904 // tr.getConn should leave it for the HTTP/2 alt to call GotConn. 3905 t.Error("GotConn called") 3906 }, 3907 }) 3908 req, _ := NewRequestWithContext(ctx, MethodGet, "https://example.com", nil) 3909 _, err := tr.RoundTrip(req) 3910 if err != errFakeRoundTrip { 3911 t.Errorf("got error: %v; want %q", err, errFakeRoundTrip) 3912 } 3913 wantIdle("after round trip", 1) 3914 } 3915 3916 func TestTransportRemovesH2ConnsAfterIdle(t *testing.T) { 3917 if testing.Short() { 3918 t.Skip("skipping in short mode") 3919 } 3920 3921 trFunc := func(tr *Transport) { 3922 tr.MaxConnsPerHost = 1 3923 tr.MaxIdleConnsPerHost = 1 3924 tr.IdleConnTimeout = 10 * time.Millisecond 3925 } 3926 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), trFunc) 3927 defer cst.close() 3928 3929 if _, err := cst.c.Get(cst.ts.URL); err != nil { 3930 t.Fatalf("got error: %s", err) 3931 } 3932 3933 time.Sleep(100 * time.Millisecond) 3934 got := make(chan error) 3935 go func() { 3936 if _, err := cst.c.Get(cst.ts.URL); err != nil { 3937 got <- err 3938 } 3939 close(got) 3940 }() 3941 3942 timeout := time.NewTimer(5 * time.Second) 3943 defer timeout.Stop() 3944 select { 3945 case err := <-got: 3946 if err != nil { 3947 t.Fatalf("got error: %s", err) 3948 } 3949 case <-timeout.C: 3950 t.Fatal("request never completed") 3951 } 3952 } 3953 3954 // This tests that a client requesting a content range won't also 3955 // implicitly ask for gzip support. If they want that, they need to do it 3956 // on their own. 3957 // golang.org/issue/8923 3958 func TestTransportRangeAndGzip(t *testing.T) { 3959 defer afterTest(t) 3960 reqc := make(chan *Request, 1) 3961 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3962 reqc <- r 3963 })) 3964 defer ts.Close() 3965 c := ts.Client() 3966 3967 req, _ := NewRequest("GET", ts.URL, nil) 3968 req.Header.Set("Range", "bytes=7-11") 3969 res, err := c.Do(req) 3970 if err != nil { 3971 t.Fatal(err) 3972 } 3973 3974 select { 3975 case r := <-reqc: 3976 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 3977 t.Error("Transport advertised gzip support in the Accept header") 3978 } 3979 if r.Header.Get("Range") == "" { 3980 t.Error("no Range in request") 3981 } 3982 case <-time.After(10 * time.Second): 3983 t.Fatal("timeout") 3984 } 3985 _ = res.Body.Close() 3986 } 3987 3988 // Test for issue 10474 3989 func TestTransportResponseCancelRace(t *testing.T) { 3990 defer afterTest(t) 3991 3992 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3993 // important that this response has a body. 3994 var b [1024]byte 3995 _, _ = w.Write(b[:]) 3996 })) 3997 defer ts.Close() 3998 tr := ts.Client().Transport.(*Transport) 3999 4000 req, err := NewRequest("GET", ts.URL, nil) 4001 if err != nil { 4002 t.Fatal(err) 4003 } 4004 res, err := tr.RoundTrip(req) 4005 if err != nil { 4006 t.Fatal(err) 4007 } 4008 // If we do an early close, Transport just throws the connection away and 4009 // doesn't reuse it. In order to trigger the bug, it has to reuse the connection 4010 // so read the body 4011 if _, err := io.Copy(io.Discard, res.Body); err != nil { 4012 t.Fatal(err) 4013 } 4014 4015 req2, err := NewRequest("GET", ts.URL, nil) 4016 if err != nil { 4017 t.Fatal(err) 4018 } 4019 tr.CancelRequest(req) 4020 res, err = tr.RoundTrip(req2) 4021 if err != nil { 4022 t.Fatal(err) 4023 } 4024 _ = res.Body.Close() 4025 } 4026 4027 // Test for issue 19248: Content-Encoding's value is case insensitive. 4028 func TestTransportContentEncodingCaseInsensitive(t *testing.T) { 4029 setParallel(t) 4030 defer afterTest(t) 4031 for _, ce := range []string{"gzip", "GZIP"} { 4032 ce := ce 4033 t.Run(ce, func(t *testing.T) { 4034 const encodedString = "Hello Gopher" 4035 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4036 w.Header().Set("Content-Encoding", ce) 4037 gz := gzip.NewWriter(w) 4038 _, _ = gz.Write([]byte(encodedString)) 4039 _ = gz.Close() 4040 })) 4041 defer ts.Close() 4042 4043 res, err := ts.Client().Get(ts.URL) 4044 if err != nil { 4045 t.Fatal(err) 4046 } 4047 4048 body, err := io.ReadAll(res.Body) 4049 _ = res.Body.Close() 4050 if err != nil { 4051 t.Fatal(err) 4052 } 4053 4054 if string(body) != encodedString { 4055 t.Fatalf("Expected body %q, got: %q\n", encodedString, string(body)) 4056 } 4057 }) 4058 } 4059 } 4060 4061 func TestTransportDialCancelRace(t *testing.T) { 4062 defer afterTest(t) 4063 4064 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 4065 defer ts.Close() 4066 tr := ts.Client().Transport.(*Transport) 4067 4068 req, err := NewRequest("GET", ts.URL, nil) 4069 if err != nil { 4070 t.Fatal(err) 4071 } 4072 SetEnterRoundTripHook(func() { 4073 tr.CancelRequest(req) 4074 }) 4075 defer SetEnterRoundTripHook(nil) 4076 res, err := tr.RoundTrip(req) 4077 if err != ExportErrRequestCanceled { 4078 t.Errorf("expected canceled request error; got %v", err) 4079 if err == nil { 4080 _ = res.Body.Close() 4081 } 4082 } 4083 } 4084 4085 // logWritesConn is a net.Conn that logs each Write call to writes 4086 // and then proxies to w. 4087 // It proxies Read calls to a reader it receives from rch. 4088 type logWritesConn struct { 4089 net.Conn // nil. crash on use. 4090 4091 w io.Writer 4092 4093 rch <-chan io.Reader 4094 r io.Reader // nil until received by rch 4095 4096 mu sync.Mutex 4097 writes []string 4098 } 4099 4100 func (c *logWritesConn) Write(p []byte) (n int, err error) { 4101 c.mu.Lock() 4102 defer c.mu.Unlock() 4103 c.writes = append(c.writes, string(p)) 4104 return c.w.Write(p) 4105 } 4106 4107 func (c *logWritesConn) Read(p []byte) (n int, err error) { 4108 if c.r == nil { 4109 c.r = <-c.rch 4110 } 4111 return c.r.Read(p) 4112 } 4113 4114 func (c *logWritesConn) Close() error { return nil } 4115 4116 // Issue 6574 4117 func TestTransportFlushesBodyChunks(t *testing.T) { 4118 defer afterTest(t) 4119 resBody := make(chan io.Reader, 1) 4120 connr, connw := io.Pipe() // connection pipe pair 4121 lw := &logWritesConn{ 4122 rch: resBody, 4123 w: connw, 4124 } 4125 tr := &Transport{ 4126 Dial: func(network, addr string) (net.Conn, error) { 4127 return lw, nil 4128 }, 4129 } 4130 bodyr, bodyw := io.Pipe() // body pipe pair 4131 go func() { 4132 defer func(bodyw *io.PipeWriter) { 4133 _ = bodyw.Close() 4134 }(bodyw) 4135 for i := 0; i < 3; i++ { 4136 _, _ = fmt.Fprintf(bodyw, "num%d\n", i) 4137 } 4138 }() 4139 resc := make(chan *Response) 4140 go func() { 4141 req, _ := NewRequest("POST", "http://localhost:8080", bodyr) 4142 req.Header.Set("User-Agent", "x") // known value for test 4143 res, err := tr.RoundTrip(req) 4144 if err != nil { 4145 t.Errorf("RoundTrip: %v", err) 4146 close(resc) 4147 return 4148 } 4149 resc <- res 4150 4151 }() 4152 // Fully consume the request before checking the Write log vs. want. 4153 req, err := ReadRequest(bufio.NewReader(connr)) 4154 if err != nil { 4155 t.Fatal(err) 4156 } 4157 _, _ = io.Copy(io.Discard, req.Body) 4158 4159 // Unblock the transport's roundTrip goroutine. 4160 resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n") 4161 res, ok := <-resc 4162 if !ok { 4163 return 4164 } 4165 defer func(Body io.ReadCloser) { 4166 _ = Body.Close() 4167 }(res.Body) 4168 4169 want := []string{ 4170 "POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n", 4171 "5\r\nnum0\n\r\n", 4172 "5\r\nnum1\n\r\n", 4173 "5\r\nnum2\n\r\n", 4174 "0\r\n\r\n", 4175 } 4176 if !reflect.DeepEqual(lw.writes, want) { 4177 t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want) 4178 } 4179 } 4180 4181 // Issue 22088: flush Transport request headers if we're not sure the body won't block on read. 4182 func TestTransportFlushesRequestHeader(t *testing.T) { 4183 defer afterTest(t) 4184 gotReq := make(chan struct{}) 4185 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 4186 close(gotReq) 4187 })) 4188 defer cst.close() 4189 4190 pr, pw := io.Pipe() 4191 req, err := NewRequest("POST", cst.ts.URL, pr) 4192 if err != nil { 4193 t.Fatal(err) 4194 } 4195 gotRes := make(chan struct{}) 4196 go func() { 4197 defer close(gotRes) 4198 res, err := cst.tr.RoundTrip(req) 4199 if err != nil { 4200 t.Error(err) 4201 return 4202 } 4203 _ = res.Body.Close() 4204 }() 4205 4206 select { 4207 case <-gotReq: 4208 _ = pw.Close() 4209 case <-time.After(5 * time.Second): 4210 t.Fatal("timeout waiting for handler to get request") 4211 } 4212 <-gotRes 4213 } 4214 4215 // Issue 11745. 4216 func TestTransportPrefersResponseOverWriteError(t *testing.T) { 4217 if testing.Short() { 4218 t.Skip("skipping in short mode") 4219 } 4220 defer afterTest(t) 4221 const contentLengthLimit = 1024 * 1024 // 1MB 4222 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4223 if r.ContentLength >= contentLengthLimit { 4224 w.WriteHeader(StatusBadRequest) 4225 _ = r.Body.Close() 4226 return 4227 } 4228 w.WriteHeader(StatusOK) 4229 })) 4230 defer ts.Close() 4231 c := ts.Client() 4232 4233 fail := 0 4234 count := 100 4235 bigBody := strings.Repeat("a", contentLengthLimit*2) 4236 for i := 0; i < count; i++ { 4237 req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody)) 4238 if err != nil { 4239 t.Fatal(err) 4240 } 4241 resp, err := c.Do(req) 4242 if err != nil { 4243 fail++ 4244 t.Logf("%d = %#v", i, err) 4245 if ue, ok := err.(*url.Error); ok { 4246 t.Logf("urlErr = %#v", ue.Err) 4247 if ne, ok := ue.Err.(*net.OpError); ok { 4248 t.Logf("netOpError = %#v", ne.Err) 4249 } 4250 } 4251 } else { 4252 _ = resp.Body.Close() 4253 if resp.StatusCode != 400 { 4254 t.Errorf("Expected status code 400, got %v", resp.Status) 4255 } 4256 } 4257 } 4258 if fail > 0 { 4259 t.Errorf("Failed %v out of %v\n", fail, count) 4260 } 4261 } 4262 4263 func TestTransportAutomaticHTTP2(t *testing.T) { 4264 testTransportAutoHTTP(t, &Transport{}, true) 4265 } 4266 4267 func TestTransportAutomaticHTTP2_DialerAndTLSConfigSupportsHTTP2AndTLSConfig(t *testing.T) { 4268 testTransportAutoHTTP(t, &Transport{ 4269 ForceAttemptHTTP2: true, 4270 TLSClientConfig: new(tls.Config), 4271 }, true) 4272 } 4273 4274 // golang.org/issue/14391: also check DefaultTransport 4275 func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) { 4276 testTransportAutoHTTP(t, DefaultTransport.(*Transport), true) 4277 } 4278 4279 func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { 4280 testTransportAutoHTTP(t, &Transport{ 4281 TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), 4282 }, false) 4283 } 4284 4285 func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { 4286 testTransportAutoHTTP(t, &Transport{ 4287 TLSClientConfig: new(tls.Config), 4288 }, false) 4289 } 4290 4291 func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { 4292 testTransportAutoHTTP(t, &Transport{ 4293 ExpectContinueTimeout: 1 * time.Second, 4294 }, true) 4295 } 4296 4297 func TestTransportAutomaticHTTP2_Dial(t *testing.T) { 4298 var d net.Dialer 4299 testTransportAutoHTTP(t, &Transport{ 4300 Dial: d.Dial, 4301 }, false) 4302 } 4303 4304 func TestTransportAutomaticHTTP2_DialContext(t *testing.T) { 4305 var d net.Dialer 4306 testTransportAutoHTTP(t, &Transport{ 4307 DialContext: d.DialContext, 4308 }, false) 4309 } 4310 4311 func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) { 4312 testTransportAutoHTTP(t, &Transport{ 4313 DialTLS: func(network, addr string) (net.Conn, error) { 4314 panic("unused") 4315 }, 4316 }, false) 4317 } 4318 4319 func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { 4320 CondSkipHTTP2(t) 4321 _, err := tr.RoundTrip(new(Request)) 4322 if err == nil { 4323 t.Error("expected error from RoundTrip") 4324 } 4325 if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { 4326 t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) 4327 } 4328 } 4329 4330 // Issue 13633: there was a race where we returned bodyless responses 4331 // to callers before recycling the persistent connection, which meant 4332 // a client doing two subsequent requests could end up on different 4333 // connections. It's somewhat harmless but enough tests assume it's 4334 // not true in order to test other things that it's worth fixing. 4335 // Plus it's nice to be consistent and not have timing-dependent 4336 // behavior. 4337 func TestTransportReuseConnEmptyResponseBody(t *testing.T) { 4338 defer afterTest(t) 4339 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 4340 w.Header().Set("X-Addr", r.RemoteAddr) 4341 // Empty response body. 4342 })) 4343 defer cst.close() 4344 n := 100 4345 if testing.Short() { 4346 n = 10 4347 } 4348 var firstAddr string 4349 for i := 0; i < n; i++ { 4350 res, err := cst.c.Get(cst.ts.URL) 4351 if err != nil { 4352 log.Fatal(err) 4353 } 4354 addr := res.Header.Get("X-Addr") 4355 if i == 0 { 4356 firstAddr = addr 4357 } else if addr != firstAddr { 4358 t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr) 4359 } 4360 _ = res.Body.Close() 4361 } 4362 } 4363 4364 // Issue 13839 4365 func TestNoCrashReturningTransportAltConn(t *testing.T) { 4366 cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) 4367 if err != nil { 4368 t.Fatal(err) 4369 } 4370 ln := newLocalListener(t) 4371 defer func(ln net.Listener) { 4372 _ = ln.Close() 4373 }(ln) 4374 4375 var wg sync.WaitGroup 4376 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done) 4377 defer SetPendingDialHooks(nil, nil) 4378 4379 testDone := make(chan struct{}) 4380 defer close(testDone) 4381 go func() { 4382 tln := tls.NewListener(ln, &tls.Config{ 4383 NextProtos: []string{"foo"}, 4384 Certificates: []tls.Certificate{cert}, 4385 }) 4386 sc, err := tln.Accept() 4387 if err != nil { 4388 t.Error(err) 4389 return 4390 } 4391 if err := sc.(*tls.Conn).Handshake(); err != nil { 4392 t.Error(err) 4393 return 4394 } 4395 <-testDone 4396 _ = sc.Close() 4397 }() 4398 4399 addr := ln.Addr().String() 4400 4401 req, _ := NewRequest("GET", "https://fake.tld/", nil) 4402 cancel := make(chan struct{}) 4403 req.Cancel = cancel 4404 4405 doReturned := make(chan bool, 1) 4406 madeRoundTripper := make(chan bool, 1) 4407 4408 tr := &Transport{ 4409 DisableKeepAlives: true, 4410 TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{ 4411 "foo": func(authority string, c *tls.Conn) RoundTripper { 4412 madeRoundTripper <- true 4413 return funcRoundTripper(func() { 4414 t.Error("foo RoundTripper should not be called") 4415 }) 4416 }, 4417 }, 4418 Dial: func(_, _ string) (net.Conn, error) { 4419 panic("shouldn't be called") 4420 }, 4421 DialTLS: func(_, _ string) (net.Conn, error) { 4422 tc, err := tls.Dial("tcp", addr, &tls.Config{ 4423 InsecureSkipVerify: true, 4424 NextProtos: []string{"foo"}, 4425 }) 4426 if err != nil { 4427 return nil, err 4428 } 4429 if err := tc.Handshake(); err != nil { 4430 return nil, err 4431 } 4432 close(cancel) 4433 <-doReturned 4434 return tc, nil 4435 }, 4436 } 4437 c := &Client{Transport: tr} 4438 4439 _, err = c.Do(req) 4440 if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn { 4441 t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err) 4442 } 4443 4444 doReturned <- true 4445 <-madeRoundTripper 4446 wg.Wait() 4447 } 4448 4449 func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) { 4450 testTransportReuseConnection_Gzip(t, true) 4451 } 4452 4453 func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) { 4454 testTransportReuseConnection_Gzip(t, false) 4455 } 4456 4457 // Make sure we re-use underlying TCP connection for gzipped responses too. 4458 //goland:noinspection GoSnakeCaseUsage 4459 func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) { 4460 setParallel(t) 4461 defer afterTest(t) 4462 addr := make(chan string, 2) 4463 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4464 addr <- r.RemoteAddr 4465 w.Header().Set("Content-Encoding", "gzip") 4466 if chunked { 4467 w.(Flusher).Flush() 4468 } 4469 _, _ = w.Write(rgz) // arbitrary gzip response 4470 })) 4471 defer ts.Close() 4472 c := ts.Client() 4473 4474 for i := 0; i < 2; i++ { 4475 res, err := c.Get(ts.URL) 4476 if err != nil { 4477 t.Fatal(err) 4478 } 4479 buf := make([]byte, len(rgz)) 4480 if n, err := io.ReadFull(res.Body, buf); err != nil { 4481 t.Errorf("%d. ReadFull = %v, %v", i, n, err) 4482 } 4483 // Note: no res.Body.Close call. It should work without it, 4484 // since the flate.Reader's internal buffering will hit EOF 4485 // and that should be sufficient. 4486 } 4487 a1, a2 := <-addr, <-addr 4488 if a1 != a2 { 4489 t.Fatalf("didn't reuse connection") 4490 } 4491 } 4492 4493 func TestTransportResponseHeaderLength(t *testing.T) { 4494 setParallel(t) 4495 defer afterTest(t) 4496 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4497 if r.URL.Path == "/long" { 4498 w.Header().Set("Long", strings.Repeat("a", 1<<20)) 4499 } 4500 })) 4501 defer ts.Close() 4502 c := ts.Client() 4503 c.Transport.(*Transport).MaxResponseHeaderBytes = 512 << 10 4504 4505 if res, err := c.Get(ts.URL); err != nil { 4506 t.Fatal(err) 4507 } else { 4508 _ = res.Body.Close() 4509 } 4510 4511 res, err := c.Get(ts.URL + "/long") 4512 if err == nil { 4513 defer func(Body io.ReadCloser) { 4514 _ = Body.Close() 4515 }(res.Body) 4516 var n int64 4517 for k, vv := range res.Header { 4518 for _, v := range vv { 4519 n += int64(len(k)) + int64(len(v)) 4520 } 4521 } 4522 t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n) 4523 } 4524 if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) { 4525 t.Errorf("got error: %v; want %q", err, want) 4526 } 4527 } 4528 4529 // func TestTransportEventTrace(t *testing.T) { testTransportEventTrace(t, h1Mode, false) } 4530 // func TestTransportEventTrace_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, false) } 4531 4532 // // test a non-nil httptrace.ClientTrace but with all hooks set to zero. 4533 // func TestTransportEventTrace_NoHooks(t *testing.T) { testTransportEventTrace(t, h1Mode, true) } 4534 // func TestTransportEventTrace_NoHooks_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, true) } 4535 4536 //goland:noinspection GoUnusedFunction 4537 func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { 4538 defer afterTest(t) 4539 const resBody = "some body" 4540 gotWroteReqEvent := make(chan struct{}, 500) 4541 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 4542 if r.Method == "GET" { 4543 // Do nothing for the second request. 4544 return 4545 } 4546 if _, err := io.ReadAll(r.Body); err != nil { 4547 t.Error(err) 4548 } 4549 if !noHooks { 4550 select { 4551 case <-gotWroteReqEvent: 4552 case <-time.After(5 * time.Second): 4553 t.Error("timeout waiting for WroteRequest event") 4554 } 4555 } 4556 _, _ = io.WriteString(w, resBody) 4557 })) 4558 defer cst.close() 4559 4560 cst.tr.ExpectContinueTimeout = 1 * time.Second 4561 4562 var mu sync.Mutex // guards buf 4563 var buf bytes.Buffer 4564 logf := func(format string, args ...interface{}) { 4565 mu.Lock() 4566 defer mu.Unlock() 4567 _, _ = fmt.Fprintf(&buf, format, args...) 4568 buf.WriteByte('\n') 4569 } 4570 4571 addrStr := cst.ts.Listener.Addr().String() 4572 ip, port, err := net.SplitHostPort(addrStr) 4573 if err != nil { 4574 t.Fatal(err) 4575 } 4576 4577 // Install a fake DNS server. 4578 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, network, host string) ([]net.IPAddr, error) { 4579 if host != "dns-is-faked.golang" { 4580 t.Errorf("unexpected DNS host lookup for %q/%q", network, host) 4581 return nil, nil 4582 } 4583 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 4584 }) 4585 4586 body := "some body" 4587 req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader(body)) 4588 req.Header["X-Foo-Multiple-Vals"] = []string{"bar", "baz"} 4589 trace := &httptrace.ClientTrace{ 4590 GetConn: func(hostPort string) { logf("Getting conn for %v ...", hostPort) }, 4591 GotConn: func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) }, 4592 GotFirstResponseByte: func() { logf("first response byte") }, 4593 PutIdleConn: func(err error) { logf("PutIdleConn = %v", err) }, 4594 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) }, 4595 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) }, 4596 ConnectStart: func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) }, 4597 ConnectDone: func(network, addr string, err error) { 4598 if err != nil { 4599 t.Errorf("ConnectDone: %v", err) 4600 } 4601 logf("ConnectDone: connected to %s %s = %v", network, addr, err) 4602 }, 4603 WroteHeaderField: func(key string, value []string) { 4604 logf("WroteHeaderField: %s: %v", key, value) 4605 }, 4606 WroteHeaders: func() { 4607 logf("WroteHeaders") 4608 }, 4609 Wait100Continue: func() { logf("Wait100Continue") }, 4610 Got100Continue: func() { logf("Got100Continue") }, 4611 WroteRequest: func(e httptrace.WroteRequestInfo) { 4612 logf("WroteRequest: %+v", e) 4613 gotWroteReqEvent <- struct{}{} 4614 }, 4615 } 4616 if h2 { 4617 trace.TLSHandshakeStart = func() { logf("tls handshake start") } 4618 trace.TLSHandshakeDone = func(s tls.ConnectionState, err error) { 4619 logf("tls handshake done. ConnectionState = %v \n err = %v", s, err) 4620 } 4621 } 4622 if noHooks { 4623 // zero out all func pointers, trying to get some path to crash 4624 *trace = httptrace.ClientTrace{} 4625 } 4626 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 4627 4628 req.Header.Set("Expect", "100-continue") 4629 res, err := cst.c.Do(req) 4630 if err != nil { 4631 t.Fatal(err) 4632 } 4633 logf("got roundtrip.response") 4634 slurp, err := io.ReadAll(res.Body) 4635 if err != nil { 4636 t.Fatal(err) 4637 } 4638 logf("consumed body") 4639 if string(slurp) != resBody || res.StatusCode != 200 { 4640 t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody) 4641 } 4642 _ = res.Body.Close() 4643 4644 if noHooks { 4645 // Done at this point. Just testing a full HTTP 4646 // requests can happen with a trace pointing to a zero 4647 // ClientTrace, full of nil func pointers. 4648 return 4649 } 4650 4651 mu.Lock() 4652 got := buf.String() 4653 mu.Unlock() 4654 4655 wantOnce := func(sub string) { 4656 if strings.Count(got, sub) != 1 { 4657 t.Errorf("expected substring %q exactly once in output.", sub) 4658 } 4659 } 4660 wantOnceOrMore := func(sub string) { 4661 if strings.Count(got, sub) == 0 { 4662 t.Errorf("expected substring %q at least once in output.", sub) 4663 } 4664 } 4665 wantOnce("Getting conn for dns-is-faked.golang:" + port) 4666 wantOnce("DNS start: {Host:dns-is-faked.golang}") 4667 wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}") 4668 wantOnce("got conn: {") 4669 wantOnceOrMore("Connecting to tcp " + addrStr) 4670 wantOnceOrMore("connected to tcp " + addrStr + " = <nil>") 4671 wantOnce("Reused:false WasIdle:false IdleTime:0s") 4672 wantOnce("first response byte") 4673 if h2 { 4674 wantOnce("tls handshake start") 4675 wantOnce("tls handshake done") 4676 } else { 4677 wantOnce("PutIdleConn = <nil>") 4678 wantOnce("WroteHeaderField: User-Agent: [Go-http-client/1.1]") 4679 // TODO(meirf): issue 19761. Make these agnostic to h1/h2. (These are not h1 specific, but the 4680 // WroteHeaderField hook is not yet implemented in h2.) 4681 wantOnce(fmt.Sprintf("WroteHeaderField: Host: [dns-is-faked.golang:%s]", port)) 4682 wantOnce(fmt.Sprintf("WroteHeaderField: Content-Length: [%d]", len(body))) 4683 wantOnce("WroteHeaderField: X-Foo-Multiple-Vals: [bar baz]") 4684 wantOnce("WroteHeaderField: Accept-Encoding: [gzip]") 4685 } 4686 wantOnce("WroteHeaders") 4687 wantOnce("Wait100Continue") 4688 wantOnce("Got100Continue") 4689 wantOnce("WroteRequest: {Err:<nil>}") 4690 if strings.Contains(got, " to udp ") { 4691 t.Errorf("should not see UDP (DNS) connections") 4692 } 4693 if t.Failed() { 4694 t.Errorf("Output:\n%s", got) 4695 } 4696 4697 // And do a second request: 4698 req, _ = NewRequest("GET", cst.scheme()+"://dns-is-faked.golang:"+port, nil) 4699 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 4700 res, err = cst.c.Do(req) 4701 if err != nil { 4702 t.Fatal(err) 4703 } 4704 if res.StatusCode != 200 { 4705 t.Fatal(res.Status) 4706 } 4707 _ = res.Body.Close() 4708 4709 mu.Lock() 4710 got = buf.String() 4711 mu.Unlock() 4712 4713 sub := "Getting conn for dns-is-faked.golang:" 4714 if gotn, want := strings.Count(got, sub), 2; gotn != want { 4715 t.Errorf("substring %q appeared %d times; want %d. Log:\n%s", sub, gotn, want, got) 4716 } 4717 4718 } 4719 4720 func TestTransportEventTraceTLSVerify(t *testing.T) { 4721 var mu sync.Mutex 4722 var buf bytes.Buffer 4723 logf := func(format string, args ...interface{}) { 4724 mu.Lock() 4725 defer mu.Unlock() 4726 _, _ = fmt.Fprintf(&buf, format, args...) 4727 buf.WriteByte('\n') 4728 } 4729 4730 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4731 t.Error("Unexpected request") 4732 })) 4733 defer ts.Close() 4734 ts.Config.ErrorLog = log.New(funcWriter(func(p []byte) (int, error) { 4735 logf("%s", p) 4736 return len(p), nil 4737 }), "", 0) 4738 4739 certpool := x509.NewCertPool() 4740 certpool.AddCert(ts.Certificate()) 4741 4742 c := &Client{Transport: &Transport{ 4743 TLSClientConfig: &tls.Config{ 4744 ServerName: "dns-is-faked.golang", 4745 RootCAs: certpool, 4746 }, 4747 }} 4748 4749 trace := &httptrace.ClientTrace{ 4750 TLSHandshakeStart: func() { logf("TLSHandshakeStart") }, 4751 TLSHandshakeDone: func(s tls.ConnectionState, err error) { 4752 logf("TLSHandshakeDone: ConnectionState = %v \n err = %v", s, err) 4753 }, 4754 } 4755 4756 req, _ := NewRequest("GET", ts.URL, nil) 4757 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 4758 _, err := c.Do(req) 4759 if err == nil { 4760 t.Error("Expected request to fail TLS verification") 4761 } 4762 4763 mu.Lock() 4764 got := buf.String() 4765 mu.Unlock() 4766 4767 wantOnce := func(sub string) { 4768 if strings.Count(got, sub) != 1 { 4769 t.Errorf("expected substring %q exactly once in output.", sub) 4770 } 4771 } 4772 4773 wantOnce("TLSHandshakeStart") 4774 wantOnce("TLSHandshakeDone") 4775 wantOnce("err = x509: certificate is valid for example.com") 4776 4777 if t.Failed() { 4778 t.Errorf("Output:\n%s", got) 4779 } 4780 } 4781 4782 var ( 4783 isDNSHijackedOnce sync.Once 4784 isDNSHijacked bool 4785 ) 4786 4787 //goland:noinspection GoUnusedFunction 4788 func skipIfDNSHijacked(t *testing.T) { 4789 // Skip this test if the user is using a shady/ISP 4790 // DNS server hijacking queries. 4791 // See issues 16732, 16716. 4792 isDNSHijackedOnce.Do(func() { 4793 addrs, _ := net.LookupHost("dns-should-not-resolve.golang") 4794 isDNSHijacked = len(addrs) != 0 4795 }) 4796 if isDNSHijacked { 4797 t.Skip("skipping; test requires non-hijacking DNS server") 4798 } 4799 } 4800 4801 // func TestTransportEventTraceRealDNS(t *testing.T) { 4802 // skipIfDNSHijacked(t) 4803 // defer afterTest(t) 4804 // tr := &Transport{} 4805 // defer tr.CloseIdleConnections() 4806 // c := &Client{Transport: tr} 4807 4808 // var mu sync.Mutex // guards buf 4809 // var buf bytes.Buffer 4810 // logf := func(format string, args ...interface{}) { 4811 // mu.Lock() 4812 // defer mu.Unlock() 4813 // fmt.Fprintf(&buf, format, args...) 4814 // buf.WriteByte('\n') 4815 // } 4816 4817 // req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil) 4818 // trace := &httptrace.ClientTrace{ 4819 // DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) }, 4820 // DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) }, 4821 // ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) }, 4822 // ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) }, 4823 // } 4824 // req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 4825 4826 // resp, err := c.Do(req) 4827 // if err == nil { 4828 // resp.Body.Close() 4829 // t.Fatal("expected error during DNS lookup") 4830 // } 4831 4832 // mu.Lock() 4833 // got := buf.String() 4834 // mu.Unlock() 4835 4836 // wantSub := func(sub string) { 4837 // if !strings.Contains(got, sub) { 4838 // t.Errorf("expected substring %q in output.", sub) 4839 // } 4840 // } 4841 // wantSub("DNSStart: {Host:dns-should-not-resolve.golang}") 4842 // wantSub("DNSDone: {Addrs:[] Err:") 4843 // if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") { 4844 // t.Errorf("should not see Connect events") 4845 // } 4846 // if t.Failed() { 4847 // t.Errorf("Output:\n%s", got) 4848 // } 4849 // } 4850 4851 // Issue 14353: port can only contain digits. 4852 func TestTransportRejectsAlphaPort(t *testing.T) { 4853 //goland:noinspection HttpUrlsUsage 4854 res, err := Get("http://dummy.tld:123foo/bar") 4855 if err == nil { 4856 _ = res.Body.Close() 4857 t.Fatal("unexpected success") 4858 } 4859 ue, ok := err.(*url.Error) 4860 if !ok { 4861 t.Fatalf("got %#v; want *url.Error", err) 4862 } 4863 got := ue.Err.Error() 4864 want := `invalid port ":123foo" after host` 4865 if got != want { 4866 t.Errorf("got error %q; want %q", got, want) 4867 } 4868 } 4869 4870 // Test the httptrace.TLSHandshake{Start,Done} hooks with a https http1 4871 // connections. The http2 test is done in TestTransportEventTrace_h2 4872 func TestTLSHandshakeTrace(t *testing.T) { 4873 defer afterTest(t) 4874 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 4875 defer ts.Close() 4876 4877 var mu sync.Mutex 4878 var start, done bool 4879 trace := &httptrace.ClientTrace{ 4880 TLSHandshakeStart: func() { 4881 mu.Lock() 4882 defer mu.Unlock() 4883 start = true 4884 }, 4885 TLSHandshakeDone: func(s tls.ConnectionState, err error) { 4886 mu.Lock() 4887 defer mu.Unlock() 4888 done = true 4889 if err != nil { 4890 t.Fatal("Expected error to be nil but was:", err) 4891 } 4892 }, 4893 } 4894 4895 c := ts.Client() 4896 req, err := NewRequest("GET", ts.URL, nil) 4897 if err != nil { 4898 t.Fatal("Unable to construct test request:", err) 4899 } 4900 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) 4901 4902 r, err := c.Do(req) 4903 if err != nil { 4904 t.Fatal("Unexpected error making request:", err) 4905 } 4906 _ = r.Body.Close() 4907 mu.Lock() 4908 defer mu.Unlock() 4909 if !start { 4910 t.Fatal("Expected TLSHandshakeStart to be called, but wasn't") 4911 } 4912 if !done { 4913 t.Fatal("Expected TLSHandshakeDone to be called, but wasnt't") 4914 } 4915 } 4916 4917 // func TestTransportMaxIdleConns(t *testing.T) { 4918 // defer afterTest(t) 4919 // ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4920 // // No body for convenience. 4921 // })) 4922 // defer ts.Close() 4923 // c := ts.Client() 4924 // tr := c.Transport.(*Transport) 4925 // tr.MaxIdleConns = 4 4926 4927 // ip, port, err := net.SplitHostPort(ts.Listener.Addr().String()) 4928 // if err != nil { 4929 // t.Fatal(err) 4930 // } 4931 // ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, _, host string) ([]net.IPAddr, error) { 4932 // return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 4933 // }) 4934 4935 // hitHost := func(n int) { 4936 // req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil) 4937 // req = req.WithContext(ctx) 4938 // res, err := c.Do(req) 4939 // if err != nil { 4940 // t.Fatal(err) 4941 // } 4942 // res.Body.Close() 4943 // } 4944 // for i := 0; i < 4; i++ { 4945 // hitHost(i) 4946 // } 4947 // want := []string{ 4948 // "|http|host-0.dns-is-faked.golang:" + port, 4949 // "|http|host-1.dns-is-faked.golang:" + port, 4950 // "|http|host-2.dns-is-faked.golang:" + port, 4951 // "|http|host-3.dns-is-faked.golang:" + port, 4952 // } 4953 // if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 4954 // t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want) 4955 // } 4956 4957 // // Now hitting the 5th host should kick out the first host: 4958 // hitHost(4) 4959 // want = []string{ 4960 // "|http|host-1.dns-is-faked.golang:" + port, 4961 // "|http|host-2.dns-is-faked.golang:" + port, 4962 // "|http|host-3.dns-is-faked.golang:" + port, 4963 // "|http|host-4.dns-is-faked.golang:" + port, 4964 // } 4965 // if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 4966 // t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want) 4967 // } 4968 // } 4969 4970 func TestTransportIdleConnTimeout_h1(t *testing.T) { testTransportIdleConnTimeout(t, h1Mode) } 4971 func TestTransportIdleConnTimeout_h2(t *testing.T) { testTransportIdleConnTimeout(t, h2Mode) } 4972 func testTransportIdleConnTimeout(t *testing.T, h2 bool) { 4973 if testing.Short() { 4974 t.Skip("skipping in short mode") 4975 } 4976 defer afterTest(t) 4977 4978 const timeout = 1 * time.Second 4979 4980 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 4981 // No body for convenience. 4982 })) 4983 defer cst.close() 4984 tr := cst.tr 4985 tr.IdleConnTimeout = timeout 4986 defer tr.CloseIdleConnections() 4987 c := &Client{Transport: tr} 4988 4989 idleConns := func() []string { 4990 if h2 { 4991 return tr.IdleConnStrsForTesting_h2() 4992 } else { 4993 return tr.IdleConnStrsForTesting() 4994 } 4995 } 4996 4997 var conn string 4998 doReq := func(n int) { 4999 req, _ := NewRequest("GET", cst.ts.URL, nil) 5000 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 5001 PutIdleConn: func(err error) { 5002 if err != nil { 5003 t.Errorf("failed to keep idle conn: %v", err) 5004 } 5005 }, 5006 })) 5007 res, err := c.Do(req) 5008 if err != nil { 5009 t.Fatal(err) 5010 } 5011 _ = res.Body.Close() 5012 conns := idleConns() 5013 if len(conns) != 1 { 5014 t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns) 5015 } 5016 if conn == "" { 5017 conn = conns[0] 5018 } 5019 if conn != conns[0] { 5020 t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n) 5021 } 5022 } 5023 for i := 0; i < 3; i++ { 5024 doReq(i) 5025 time.Sleep(timeout / 2) 5026 } 5027 time.Sleep(timeout * 3 / 2) 5028 if got := idleConns(); len(got) != 0 { 5029 t.Errorf("idle conns = %q; want none", got) 5030 } 5031 } 5032 5033 // Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an 5034 // HTTP/2 connection was established but its caller no longer 5035 // wanted it. (Assuming the connection cache was enabled, which it is 5036 // by default) 5037 // 5038 // This test reproduced the crash by setting the IdleConnTimeout low 5039 // (to make the test reasonable) and then making a request which is 5040 // canceled by the DialTLS hook, which then also waits to return the 5041 // real connection until after the RoundTrip saw the error. Then we 5042 // know the successful tls.Dial from DialTLS will need to go into the 5043 // idle pool. Then we give it a of time to explode. 5044 func TestIdleConnH2Crash(t *testing.T) { 5045 setParallel(t) 5046 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 5047 // nothing 5048 })) 5049 defer cst.close() 5050 5051 ctx, cancel := context.WithCancel(context.Background()) 5052 defer cancel() 5053 5054 sawDoErr := make(chan bool, 1) 5055 testDone := make(chan struct{}) 5056 defer close(testDone) 5057 5058 cst.tr.IdleConnTimeout = 5 * time.Millisecond 5059 cst.tr.DialTLS = func(network, addr string) (net.Conn, error) { 5060 c, err := tls.Dial(network, addr, &tls.Config{ 5061 InsecureSkipVerify: true, 5062 NextProtos: []string{"h2"}, 5063 }) 5064 if err != nil { 5065 t.Error(err) 5066 return nil, err 5067 } 5068 if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" { 5069 t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2") 5070 _ = c.Close() 5071 return nil, errors.New("bogus") 5072 } 5073 5074 cancel() 5075 5076 failTimer := time.NewTimer(5 * time.Second) 5077 defer failTimer.Stop() 5078 select { 5079 case <-sawDoErr: 5080 case <-testDone: 5081 case <-failTimer.C: 5082 t.Error("timeout in DialTLS, waiting too long for cst.c.Do to fail") 5083 } 5084 return c, nil 5085 } 5086 5087 req, _ := NewRequest("GET", cst.ts.URL, nil) 5088 req = req.WithContext(ctx) 5089 res, err := cst.c.Do(req) 5090 if err == nil { 5091 _ = res.Body.Close() 5092 t.Fatal("unexpected success") 5093 } 5094 sawDoErr <- true 5095 5096 // Wait for the explosion. 5097 time.Sleep(cst.tr.IdleConnTimeout * 10) 5098 } 5099 5100 type funcConn struct { 5101 net.Conn 5102 read func([]byte) (int, error) 5103 write func([]byte) (int, error) 5104 } 5105 5106 func (c funcConn) Read(p []byte) (int, error) { return c.read(p) } 5107 func (c funcConn) Write(p []byte) (int, error) { return c.write(p) } 5108 func (c funcConn) Close() error { return nil } 5109 5110 // Issue 16465: Transport.RoundTrip should return the raw net.Conn.Read error from Peek 5111 // back to the caller. 5112 func TestTransportReturnsPeekError(t *testing.T) { 5113 errValue := errors.New("specific error value") 5114 5115 wrote := make(chan struct{}) 5116 var wroteOnce sync.Once 5117 5118 tr := &Transport{ 5119 Dial: func(network, addr string) (net.Conn, error) { 5120 c := funcConn{ 5121 read: func([]byte) (int, error) { 5122 <-wrote 5123 return 0, errValue 5124 }, 5125 write: func(p []byte) (int, error) { 5126 wroteOnce.Do(func() { close(wrote) }) 5127 return len(p), nil 5128 }, 5129 } 5130 return c, nil 5131 }, 5132 } 5133 _, err := tr.RoundTrip(httptest.NewRequest("GET", "http://fake.tld/", nil)) 5134 if err != errValue { 5135 t.Errorf("error = %#v; want %v", err, errValue) 5136 } 5137 } 5138 5139 // Issue 13835: international domain names should work 5140 // func TestTransportIDNA_h1(t *testing.T) { testTransportIDNA(t, h1Mode) } 5141 // func TestTransportIDNA_h2(t *testing.T) { testTransportIDNA(t, h2Mode) } 5142 //goland:noinspection GoUnusedFunction 5143 func testTransportIDNA(t *testing.T, h2 bool) { 5144 defer afterTest(t) 5145 5146 const uniDomain = "гофер.го" 5147 const punyDomain = "xn--c1ae0ajs.xn--c1aw" 5148 5149 var port string 5150 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 5151 want := punyDomain + ":" + port 5152 if r.Host != want { 5153 t.Errorf("Host header = %q; want %q", r.Host, want) 5154 } 5155 if h2 { 5156 if r.TLS == nil { 5157 t.Errorf("r.TLS == nil") 5158 } else if r.TLS.ServerName != punyDomain { 5159 t.Errorf("TLS.ServerName = %q; want %q", r.TLS.ServerName, punyDomain) 5160 } 5161 } 5162 w.Header().Set("Hit-Handler", "1") 5163 })) 5164 defer cst.close() 5165 5166 ip, port, err := net.SplitHostPort(cst.ts.Listener.Addr().String()) 5167 if err != nil { 5168 t.Fatal(err) 5169 } 5170 5171 // Install a fake DNS server. 5172 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, network, host string) ([]net.IPAddr, error) { 5173 if host != punyDomain { 5174 t.Errorf("got DNS host lookup for %q/%q; want %q", network, host, punyDomain) 5175 return nil, nil 5176 } 5177 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 5178 }) 5179 5180 req, _ := NewRequest("GET", cst.scheme()+"://"+uniDomain+":"+port, nil) 5181 trace := &httptrace.ClientTrace{ 5182 GetConn: func(hostPort string) { 5183 want := net.JoinHostPort(punyDomain, port) 5184 if hostPort != want { 5185 t.Errorf("getting conn for %q; want %q", hostPort, want) 5186 } 5187 }, 5188 DNSStart: func(e httptrace.DNSStartInfo) { 5189 if e.Host != punyDomain { 5190 t.Errorf("DNSStart Host = %q; want %q", e.Host, punyDomain) 5191 } 5192 }, 5193 } 5194 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 5195 5196 res, err := cst.tr.RoundTrip(req) 5197 if err != nil { 5198 t.Fatal(err) 5199 } 5200 defer func(Body io.ReadCloser) { 5201 _ = Body.Close() 5202 }(res.Body) 5203 if res.Header.Get("Hit-Handler") != "1" { 5204 out, err := httputil.DumpResponse(res, true) 5205 if err != nil { 5206 t.Fatal(err) 5207 } 5208 t.Errorf("Response body wasn't from Handler. Got:\n%s\n", out) 5209 } 5210 } 5211 5212 // Issue 13290: send User-Agent in proxy CONNECT 5213 func TestTransportProxyConnectHeader(t *testing.T) { 5214 defer afterTest(t) 5215 reqc := make(chan *Request, 1) 5216 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 5217 if r.Method != "CONNECT" { 5218 t.Errorf("method = %q; want CONNECT", r.Method) 5219 } 5220 reqc <- r 5221 c, _, err := w.(Hijacker).Hijack() 5222 if err != nil { 5223 t.Errorf("Hijack: %v", err) 5224 return 5225 } 5226 _ = c.Close() 5227 })) 5228 defer ts.Close() 5229 5230 c := ts.Client() 5231 c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) { 5232 return url.Parse(ts.URL) 5233 } 5234 c.Transport.(*Transport).ProxyConnectHeader = Header{ 5235 "User-Agent": {"foo"}, 5236 "Other": {"bar"}, 5237 } 5238 5239 res, err := c.Get("https://dummy.tld/") // https to force a CONNECT 5240 if err == nil { 5241 _ = res.Body.Close() 5242 t.Errorf("unexpected success") 5243 } 5244 select { 5245 case <-time.After(3 * time.Second): 5246 t.Fatal("timeout") 5247 case r := <-reqc: 5248 if got, want := r.Header.Get("User-Agent"), "foo"; got != want { 5249 t.Errorf("CONNECT request User-Agent = %q; want %q", got, want) 5250 } 5251 if got, want := r.Header.Get("Other"), "bar"; got != want { 5252 t.Errorf("CONNECT request Other = %q; want %q", got, want) 5253 } 5254 } 5255 } 5256 5257 func TestTransportProxyGetConnectHeader(t *testing.T) { 5258 defer afterTest(t) 5259 reqc := make(chan *Request, 1) 5260 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 5261 if r.Method != "CONNECT" { 5262 t.Errorf("method = %q; want CONNECT", r.Method) 5263 } 5264 reqc <- r 5265 c, _, err := w.(Hijacker).Hijack() 5266 if err != nil { 5267 t.Errorf("Hijack: %v", err) 5268 return 5269 } 5270 _ = c.Close() 5271 })) 5272 defer ts.Close() 5273 5274 c := ts.Client() 5275 c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) { 5276 return url.Parse(ts.URL) 5277 } 5278 // These should be ignored: 5279 c.Transport.(*Transport).ProxyConnectHeader = Header{ 5280 "User-Agent": {"foo"}, 5281 "Other": {"bar"}, 5282 } 5283 c.Transport.(*Transport).GetProxyConnectHeader = func(ctx context.Context, proxyURL *url.URL, target string) (Header, error) { 5284 return Header{ 5285 "User-Agent": {"foo2"}, 5286 "Other": {"bar2"}, 5287 }, nil 5288 } 5289 5290 res, err := c.Get("https://dummy.tld/") // https to force a CONNECT 5291 if err == nil { 5292 _ = res.Body.Close() 5293 t.Errorf("unexpected success") 5294 } 5295 select { 5296 case <-time.After(3 * time.Second): 5297 t.Fatal("timeout") 5298 case r := <-reqc: 5299 if got, want := r.Header.Get("User-Agent"), "foo2"; got != want { 5300 t.Errorf("CONNECT request User-Agent = %q; want %q", got, want) 5301 } 5302 if got, want := r.Header.Get("Other"), "bar2"; got != want { 5303 t.Errorf("CONNECT request Other = %q; want %q", got, want) 5304 } 5305 } 5306 } 5307 5308 var errFakeRoundTrip = errors.New("fake roundtrip") 5309 5310 type funcRoundTripper func() 5311 5312 func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) { 5313 fn() 5314 return nil, errFakeRoundTrip 5315 } 5316 5317 func wantBody(res *Response, err error, want string) error { 5318 if err != nil { 5319 return err 5320 } 5321 slurp, err := io.ReadAll(res.Body) 5322 if err != nil { 5323 return fmt.Errorf("error reading body: %v", err) 5324 } 5325 if string(slurp) != want { 5326 return fmt.Errorf("body = %q; want %q", slurp, want) 5327 } 5328 if err := res.Body.Close(); err != nil { 5329 return fmt.Errorf("body Close = %v", err) 5330 } 5331 return nil 5332 } 5333 5334 func newLocalListener(t *testing.T) net.Listener { 5335 ln, err := net.Listen("tcp", "127.0.0.1:0") 5336 if err != nil { 5337 ln, err = net.Listen("tcp6", "[::1]:0") 5338 } 5339 if err != nil { 5340 t.Fatal(err) 5341 } 5342 return ln 5343 } 5344 5345 type countCloseReader struct { 5346 n *int 5347 io.Reader 5348 } 5349 5350 func (cr countCloseReader) Close() error { 5351 *cr.n++ 5352 return nil 5353 } 5354 5355 // rgz is a gzip quine that uncompresses to itself. 5356 var rgz = []byte{ 5357 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 5358 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 5359 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 5360 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 5361 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 5362 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 5363 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 5364 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 5365 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 5366 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 5367 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 5368 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 5369 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 5370 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 5371 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 5372 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 5373 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 5374 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 5375 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 5376 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 5377 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 5378 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 5379 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 5380 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 5381 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 5382 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 5383 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 5384 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 5385 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 5386 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 5387 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 5388 0x00, 0x00, 5389 } 5390 5391 // Ensure that a missing status doesn't make the server panic 5392 // See Issue https://golang.org/issues/21701 5393 func TestMissingStatusNoPanic(t *testing.T) { 5394 t.Parallel() 5395 5396 const want = "unknown status code" 5397 5398 ln := newLocalListener(t) 5399 addr := ln.Addr().String() 5400 done := make(chan bool) 5401 //goland:noinspection HttpUrlsUsage 5402 fullAddrURL := fmt.Sprintf("http://%s", addr) 5403 raw := "HTTP/1.1 400\r\n" + 5404 "Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" + 5405 "Content-Type: text/html; charset=utf-8\r\n" + 5406 "Content-Length: 10\r\n" + 5407 "Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT\r\n" + 5408 "Vary: Accept-Encoding\r\n\r\n" + 5409 "Aloha Olaa" 5410 5411 go func() { 5412 defer close(done) 5413 5414 conn, _ := ln.Accept() 5415 if conn != nil { 5416 _, _ = io.WriteString(conn, raw) 5417 _, _ = io.ReadAll(conn) 5418 _ = conn.Close() 5419 } 5420 }() 5421 5422 proxyURL, err := url.Parse(fullAddrURL) 5423 if err != nil { 5424 t.Fatalf("proxyURL: %v", err) 5425 } 5426 5427 tr := &Transport{Proxy: ProxyURL(proxyURL)} 5428 5429 req, _ := NewRequest("GET", "https://golang.org/", nil) 5430 res, err, panicked := doFetchCheckPanic(tr, req) 5431 if panicked { 5432 t.Error("panicked, expecting an error") 5433 } 5434 if res != nil && res.Body != nil { 5435 _, _ = io.Copy(io.Discard, res.Body) 5436 _ = res.Body.Close() 5437 } 5438 5439 if err == nil || !strings.Contains(err.Error(), want) { 5440 t.Errorf("got=%v want=%q", err, want) 5441 } 5442 5443 _ = ln.Close() 5444 <-done 5445 } 5446 5447 func doFetchCheckPanic(tr *Transport, req *Request) (res *Response, err error, panicked bool) { 5448 defer func() { 5449 if r := recover(); r != nil { 5450 panicked = true 5451 } 5452 }() 5453 res, err = tr.RoundTrip(req) 5454 return 5455 } 5456 5457 // Issue 22330: do not allow the response body to be read when the status code 5458 // forbids a response body. 5459 func TestNoBodyOnChunked304Response(t *testing.T) { 5460 defer afterTest(t) 5461 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 5462 conn, buf, _ := w.(Hijacker).Hijack() 5463 _, _ = buf.Write([]byte("HTTP/1.1 304 NOT MODIFIED\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n")) 5464 _ = buf.Flush() 5465 _ = conn.Close() 5466 })) 5467 defer cst.close() 5468 5469 // Our test server above is sending back bogus data after the 5470 // response (the "0\r\n\r\n" part), which causes the Transport 5471 // code to log spam. Disable keep-alives so we never even try 5472 // to reuse the connection. 5473 cst.tr.DisableKeepAlives = true 5474 5475 res, err := cst.c.Get(cst.ts.URL) 5476 if err != nil { 5477 t.Fatal(err) 5478 } 5479 5480 if res.Body != NoBody { 5481 t.Errorf("Unexpected body on 304 response") 5482 } 5483 } 5484 5485 type funcWriter func([]byte) (int, error) 5486 5487 func (f funcWriter) Write(p []byte) (int, error) { return f(p) } 5488 5489 type doneContext struct { 5490 context.Context 5491 err error 5492 } 5493 5494 func (doneContext) Done() <-chan struct{} { 5495 c := make(chan struct{}) 5496 close(c) 5497 return c 5498 } 5499 5500 func (d doneContext) Err() error { return d.err } 5501 5502 // Issue 25852: Transport should check whether Context is done early. 5503 func TestTransportCheckContextDoneEarly(t *testing.T) { 5504 tr := &Transport{} 5505 req, _ := NewRequest("GET", "http://fake.example/", nil) 5506 wantErr := errors.New("some error") 5507 req = req.WithContext(doneContext{context.Background(), wantErr}) 5508 _, err := tr.RoundTrip(req) 5509 if err != wantErr { 5510 t.Errorf("error = %v; want %v", err, wantErr) 5511 } 5512 } 5513 5514 // Issue 23399: verify that if a client request times out, the Transport's 5515 // conn is closed so that it's not reused. 5516 // 5517 // This is the test variant that times out before the server replies with 5518 // any response headers. 5519 func TestClientTimeoutKillsConn_BeforeHeaders(t *testing.T) { 5520 setParallel(t) 5521 defer afterTest(t) 5522 inHandler := make(chan net.Conn, 1) 5523 handlerReadReturned := make(chan bool, 1) 5524 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 5525 conn, _, err := w.(Hijacker).Hijack() 5526 if err != nil { 5527 t.Error(err) 5528 return 5529 } 5530 inHandler <- conn 5531 n, err := conn.Read([]byte{0}) 5532 if n != 0 || err != io.EOF { 5533 t.Errorf("unexpected Read result: %v, %v", n, err) 5534 } 5535 handlerReadReturned <- true 5536 })) 5537 defer cst.close() 5538 5539 const timeout = 50 * time.Millisecond 5540 cst.c.Timeout = timeout 5541 5542 _, err := cst.c.Get(cst.ts.URL) 5543 if err == nil { 5544 t.Fatal("unexpected Get succeess") 5545 } 5546 5547 select { 5548 case c := <-inHandler: 5549 select { 5550 case <-handlerReadReturned: 5551 // Success. 5552 return 5553 case <-time.After(5 * time.Second): 5554 t.Error("Handler's conn.Read seems to be stuck in Read") 5555 _ = c.Close() // close it to unblock Handler 5556 } 5557 case <-time.After(timeout * 10): 5558 // If we didn't get into the Handler in 50ms, that probably means 5559 // the builder was just slow and the Get failed in that time 5560 // but never made it to the server. That's fine. We'll usually 5561 // test the part above on faster machines. 5562 t.Skip("skipping test on slow builder") 5563 } 5564 } 5565 5566 // Issue 23399: verify that if a client request times out, the Transport's 5567 // conn is closed so that it's not reused. 5568 // 5569 // This is the test variant that has the server send response headers 5570 // first, and time out during the write of the response body. 5571 func TestClientTimeoutKillsConn_AfterHeaders(t *testing.T) { 5572 setParallel(t) 5573 defer afterTest(t) 5574 inHandler := make(chan net.Conn, 1) 5575 handlerResult := make(chan error, 1) 5576 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 5577 w.Header().Set("Content-Length", "100") 5578 w.(Flusher).Flush() 5579 conn, _, err := w.(Hijacker).Hijack() 5580 if err != nil { 5581 t.Error(err) 5582 return 5583 } 5584 _, _ = conn.Write([]byte("foo")) 5585 inHandler <- conn 5586 n, err := conn.Read([]byte{0}) 5587 // The error should be io.EOF or "read tcp 5588 // 127.0.0.1:35827->127.0.0.1:40290: read: connection 5589 // reset by peer" depending on timing. Really we just 5590 // care that it returns at all. But if it returns with 5591 // data, that's weird. 5592 if n != 0 || err == nil { 5593 handlerResult <- fmt.Errorf("unexpected Read result: %v, %v", n, err) 5594 return 5595 } 5596 handlerResult <- nil 5597 })) 5598 defer cst.close() 5599 5600 // Set Timeout to something very long but non-zero to exercise 5601 // the codepaths that check for it. But rather than wait for it to fire 5602 // (which would make the test slow), we send on the req.Cancel channel instead, 5603 // which happens to exercise the same code paths. 5604 cst.c.Timeout = time.Minute // just to be non-zero, not to hit it. 5605 req, _ := NewRequest("GET", cst.ts.URL, nil) 5606 cancel := make(chan struct{}) 5607 req.Cancel = cancel 5608 5609 res, err := cst.c.Do(req) 5610 if err != nil { 5611 select { 5612 case <-inHandler: 5613 t.Fatalf("Get error: %v", err) 5614 default: 5615 // Failed before entering handler. Ignore result. 5616 t.Skip("skipping test on slow builder") 5617 } 5618 } 5619 5620 close(cancel) 5621 got, err := io.ReadAll(res.Body) 5622 if err == nil { 5623 t.Fatalf("unexpected success; read %q, nil", got) 5624 } 5625 5626 select { 5627 case c := <-inHandler: 5628 select { 5629 case err := <-handlerResult: 5630 if err != nil { 5631 t.Errorf("handler: %v", err) 5632 } 5633 return 5634 case <-time.After(5 * time.Second): 5635 t.Error("Handler's conn.Read seems to be stuck in Read") 5636 _ = c.Close() // close it to unblock Handler 5637 } 5638 case <-time.After(5 * time.Second): 5639 t.Fatal("timeout") 5640 } 5641 } 5642 5643 func TestTransportResponseBodyWritableOnProtocolSwitch(t *testing.T) { 5644 setParallel(t) 5645 defer afterTest(t) 5646 done := make(chan struct{}) 5647 defer close(done) 5648 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 5649 conn, _, err := w.(Hijacker).Hijack() 5650 if err != nil { 5651 t.Error(err) 5652 return 5653 } 5654 defer func(conn net.Conn) { 5655 _ = conn.Close() 5656 }(conn) 5657 _, _ = io.WriteString(conn, "HTTP/1.1 101 Switching Protocols Hi\r\nConnection: upgRADe\r\nUpgrade: foo\r\n\r\nSome buffered data\n") 5658 bs := bufio.NewScanner(conn) 5659 bs.Scan() 5660 _, _ = fmt.Fprintf(conn, "%s\n", strings.ToUpper(bs.Text())) 5661 <-done 5662 })) 5663 defer cst.close() 5664 5665 req, _ := NewRequest("GET", cst.ts.URL, nil) 5666 req.Header.Set("Upgrade", "foo") 5667 req.Header.Set("Connection", "upgrade") 5668 res, err := cst.c.Do(req) 5669 if err != nil { 5670 t.Fatal(err) 5671 } 5672 if res.StatusCode != 101 { 5673 t.Fatalf("expected 101 switching protocols; got %v, %v", res.Status, res.Header) 5674 } 5675 rwc, ok := res.Body.(io.ReadWriteCloser) 5676 if !ok { 5677 t.Fatalf("expected a ReadWriteCloser; got a %T", res.Body) 5678 } 5679 defer func(rwc io.ReadWriteCloser) { 5680 _ = rwc.Close() 5681 }(rwc) 5682 bs := bufio.NewScanner(rwc) 5683 if !bs.Scan() { 5684 t.Fatalf("expected readable input") 5685 } 5686 if got, want := bs.Text(), "Some buffered data"; got != want { 5687 t.Errorf("read %q; want %q", got, want) 5688 } 5689 _, _ = io.WriteString(rwc, "echo\n") 5690 if !bs.Scan() { 5691 t.Fatalf("expected another line") 5692 } 5693 if got, want := bs.Text(), "ECHO"; got != want { 5694 t.Errorf("read %q; want %q", got, want) 5695 } 5696 } 5697 5698 func TestTransportCONNECTBidi(t *testing.T) { 5699 defer afterTest(t) 5700 const target = "backend:443" 5701 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 5702 if r.Method != "CONNECT" { 5703 t.Errorf("unexpected method %q", r.Method) 5704 w.WriteHeader(500) 5705 return 5706 } 5707 if r.RequestURI != target { 5708 t.Errorf("unexpected CONNECT target %q", r.RequestURI) 5709 w.WriteHeader(500) 5710 return 5711 } 5712 nc, brw, err := w.(Hijacker).Hijack() 5713 if err != nil { 5714 t.Error(err) 5715 return 5716 } 5717 defer func(nc net.Conn) { 5718 _ = nc.Close() 5719 }(nc) 5720 _, _ = nc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")) 5721 // Switch to a little protocol that capitalize its input lines: 5722 for { 5723 line, err := brw.ReadString('\n') 5724 if err != nil { 5725 if err != io.EOF { 5726 t.Error(err) 5727 } 5728 return 5729 } 5730 _, _ = io.WriteString(brw, strings.ToUpper(line)) 5731 _ = brw.Flush() 5732 } 5733 })) 5734 defer cst.close() 5735 pr, pw := io.Pipe() 5736 defer func(pw *io.PipeWriter) { 5737 _ = pw.Close() 5738 }(pw) 5739 req, err := NewRequest("CONNECT", cst.ts.URL, pr) 5740 if err != nil { 5741 t.Fatal(err) 5742 } 5743 req.URL.Opaque = target 5744 res, err := cst.c.Do(req) 5745 if err != nil { 5746 t.Fatal(err) 5747 } 5748 defer func(Body io.ReadCloser) { 5749 _ = Body.Close() 5750 }(res.Body) 5751 if res.StatusCode != 200 { 5752 t.Fatalf("status code = %d; want 200", res.StatusCode) 5753 } 5754 br := bufio.NewReader(res.Body) 5755 for _, str := range []string{"foo", "bar", "baz"} { 5756 _, _ = fmt.Fprintf(pw, "%s\n", str) 5757 got, err := br.ReadString('\n') 5758 if err != nil { 5759 t.Fatal(err) 5760 } 5761 got = strings.TrimSpace(got) 5762 want := strings.ToUpper(str) 5763 if got != want { 5764 t.Fatalf("got %q; want %q", got, want) 5765 } 5766 } 5767 } 5768 5769 func TestTransportRequestReplayable(t *testing.T) { 5770 someBody := io.NopCloser(strings.NewReader("")) 5771 tests := []struct { 5772 name string 5773 req *Request 5774 want bool 5775 }{ 5776 { 5777 name: "GET", 5778 req: &Request{Method: "GET"}, 5779 want: true, 5780 }, 5781 { 5782 name: "GET_http.NoBody", 5783 req: &Request{Method: "GET", Body: NoBody}, 5784 want: true, 5785 }, 5786 { 5787 name: "GET_body", 5788 req: &Request{Method: "GET", Body: someBody}, 5789 want: false, 5790 }, 5791 { 5792 name: "POST", 5793 req: &Request{Method: "POST"}, 5794 want: false, 5795 }, 5796 { 5797 name: "POST_idempotency-key", 5798 req: &Request{Method: "POST", Header: Header{"Idempotency-Key": {"x"}}}, 5799 want: true, 5800 }, 5801 { 5802 name: "POST_x-idempotency-key", 5803 req: &Request{Method: "POST", Header: Header{"X-Idempotency-Key": {"x"}}}, 5804 want: true, 5805 }, 5806 { 5807 name: "POST_body", 5808 req: &Request{Method: "POST", Header: Header{"Idempotency-Key": {"x"}}, Body: someBody}, 5809 want: false, 5810 }, 5811 } 5812 for _, tt := range tests { 5813 t.Run(tt.name, func(t *testing.T) { 5814 got := tt.req.ExportIsReplayable() 5815 if got != tt.want { 5816 t.Errorf("replyable = %v; want %v", got, tt.want) 5817 } 5818 }) 5819 } 5820 } 5821 5822 // testMockTCPConn is a mock TCP connection used to test that 5823 // ReadFrom is called when sending the request body. 5824 type testMockTCPConn struct { 5825 *net.TCPConn 5826 5827 ReadFromCalled bool 5828 } 5829 5830 func (c *testMockTCPConn) ReadFrom(r io.Reader) (int64, error) { 5831 c.ReadFromCalled = true 5832 return c.TCPConn.ReadFrom(r) 5833 } 5834 5835 func TestTransportRequestWriteRoundTrip(t *testing.T) { 5836 nBytes := int64(1 << 10) 5837 newFileFunc := func() (r io.Reader, done func(), err error) { 5838 f, err := os.CreateTemp("", "net-http-newfilefunc") 5839 if err != nil { 5840 return nil, nil, err 5841 } 5842 5843 // Write some bytes to the file to enable reading. 5844 if _, err := io.CopyN(f, rand.Reader, nBytes); err != nil { 5845 return nil, nil, fmt.Errorf("failed to write data to file: %v", err) 5846 } 5847 if _, err := f.Seek(0, 0); err != nil { 5848 return nil, nil, fmt.Errorf("failed to seek to front: %v", err) 5849 } 5850 5851 done = func() { 5852 _ = f.Close() 5853 _ = os.Remove(f.Name()) 5854 } 5855 5856 return f, done, nil 5857 } 5858 5859 newBufferFunc := func() (io.Reader, func(), error) { 5860 return bytes.NewBuffer(make([]byte, nBytes)), func() {}, nil 5861 } 5862 5863 cases := []struct { 5864 name string 5865 readerFunc func() (io.Reader, func(), error) 5866 contentLength int64 5867 expectedReadFrom bool 5868 }{ 5869 { 5870 name: "file, length", 5871 readerFunc: newFileFunc, 5872 contentLength: nBytes, 5873 expectedReadFrom: true, 5874 }, 5875 { 5876 name: "file, no length", 5877 readerFunc: newFileFunc, 5878 }, 5879 { 5880 name: "file, negative length", 5881 readerFunc: newFileFunc, 5882 contentLength: -1, 5883 }, 5884 { 5885 name: "buffer", 5886 contentLength: nBytes, 5887 readerFunc: newBufferFunc, 5888 }, 5889 { 5890 name: "buffer, no length", 5891 readerFunc: newBufferFunc, 5892 }, 5893 { 5894 name: "buffer, length -1", 5895 contentLength: -1, 5896 readerFunc: newBufferFunc, 5897 }, 5898 } 5899 5900 for _, tc := range cases { 5901 t.Run(tc.name, func(t *testing.T) { 5902 r, cleanup, err := tc.readerFunc() 5903 if err != nil { 5904 t.Fatal(err) 5905 } 5906 defer cleanup() 5907 5908 tConn := &testMockTCPConn{} 5909 trFunc := func(tr *Transport) { 5910 tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { 5911 var d net.Dialer 5912 conn, err := d.DialContext(ctx, network, addr) 5913 if err != nil { 5914 return nil, err 5915 } 5916 5917 tcpConn, ok := conn.(*net.TCPConn) 5918 if !ok { 5919 return nil, fmt.Errorf("%s/%s does not provide a *net.TCPConn", network, addr) 5920 } 5921 5922 tConn.TCPConn = tcpConn 5923 return tConn, nil 5924 } 5925 } 5926 5927 cst := newClientServerTest( 5928 t, 5929 h1Mode, 5930 HandlerFunc(func(w ResponseWriter, r *Request) { 5931 _, _ = io.Copy(io.Discard, r.Body) 5932 _ = r.Body.Close() 5933 w.WriteHeader(200) 5934 }), 5935 trFunc, 5936 ) 5937 defer cst.close() 5938 5939 req, err := NewRequest("PUT", cst.ts.URL, r) 5940 if err != nil { 5941 t.Fatal(err) 5942 } 5943 req.ContentLength = tc.contentLength 5944 req.Header.Set("Content-Type", "application/octet-stream") 5945 resp, err := cst.c.Do(req) 5946 if err != nil { 5947 t.Fatal(err) 5948 } 5949 defer func(Body io.ReadCloser) { 5950 _ = Body.Close() 5951 }(resp.Body) 5952 if resp.StatusCode != 200 { 5953 t.Fatalf("status code = %d; want 200", resp.StatusCode) 5954 } 5955 5956 if !tConn.ReadFromCalled && tc.expectedReadFrom { 5957 t.Fatalf("did not call ReadFrom") 5958 } 5959 5960 if tConn.ReadFromCalled && !tc.expectedReadFrom { 5961 t.Fatalf("ReadFrom was unexpectedly invoked") 5962 } 5963 }) 5964 } 5965 } 5966 5967 func TestTransportClone(t *testing.T) { 5968 tr := &Transport{ 5969 Proxy: func(*Request) (*url.URL, error) { panic("") }, 5970 DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { panic("") }, 5971 Dial: func(network, addr string) (net.Conn, error) { panic("") }, 5972 DialTLS: func(network, addr string) (net.Conn, error) { panic("") }, 5973 DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { panic("") }, 5974 TLSClientConfig: new(tls.Config), 5975 TLSHandshakeTimeout: time.Second, 5976 DisableKeepAlives: true, 5977 DisableCompression: true, 5978 MaxIdleConns: 1, 5979 MaxIdleConnsPerHost: 1, 5980 MaxConnsPerHost: 1, 5981 IdleConnTimeout: time.Second, 5982 ResponseHeaderTimeout: time.Second, 5983 ExpectContinueTimeout: time.Second, 5984 ProxyConnectHeader: Header{}, 5985 GetProxyConnectHeader: func(context.Context, *url.URL, string) (Header, error) { return nil, nil }, 5986 MaxResponseHeaderBytes: 1, 5987 ForceAttemptHTTP2: true, 5988 TLSNextProto: map[string]func(authority string, c *tls.Conn) RoundTripper{ 5989 "foo": func(authority string, c *tls.Conn) RoundTripper { panic("") }, 5990 }, 5991 ReadBufferSize: 1, 5992 WriteBufferSize: 1, 5993 } 5994 tr2 := tr.Clone() 5995 rv := reflect.ValueOf(tr2).Elem() 5996 rt := rv.Type() 5997 for i := 0; i < rt.NumField(); i++ { 5998 sf := rt.Field(i) 5999 if !token.IsExported(sf.Name) { 6000 continue 6001 } 6002 if rv.Field(i).IsZero() { 6003 t.Errorf("cloned field t2.%s is zero", sf.Name) 6004 } 6005 } 6006 6007 if _, ok := tr2.TLSNextProto["foo"]; !ok { 6008 t.Errorf("cloned Transport lacked TLSNextProto 'foo' key") 6009 } 6010 6011 // But test that a nil TLSNextProto is kept nil: 6012 tr = new(Transport) 6013 tr2 = tr.Clone() 6014 if tr2.TLSNextProto != nil { 6015 t.Errorf("Transport.TLSNextProto unexpected non-nil") 6016 } 6017 } 6018 6019 func TestIs408(t *testing.T) { 6020 tests := []struct { 6021 in string 6022 want bool 6023 }{ 6024 {"HTTP/1.0 408", true}, 6025 {"HTTP/1.1 408", true}, 6026 {"HTTP/1.8 408", true}, 6027 {"HTTP/2.0 408", false}, // maybe h2c would do this? but false for now. 6028 {"HTTP/1.1 408 ", true}, 6029 {"HTTP/1.1 40", false}, 6030 {"http/1.0 408", false}, 6031 {"HTTP/1-1 408", false}, 6032 } 6033 for _, tt := range tests { 6034 if got := Export_is408Message([]byte(tt.in)); got != tt.want { 6035 t.Errorf("is408Message(%q) = %v; want %v", tt.in, got, tt.want) 6036 } 6037 } 6038 } 6039 6040 func TestTransportIgnores408(t *testing.T) { 6041 // Not parallel. Relies on mutating the log package's global Output. 6042 defer log.SetOutput(log.Writer()) 6043 6044 var logout bytes.Buffer 6045 log.SetOutput(&logout) 6046 6047 defer afterTest(t) 6048 //goland:noinspection GoUnusedConst 6049 const target = "backend:443" 6050 6051 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 6052 nc, _, err := w.(Hijacker).Hijack() 6053 if err != nil { 6054 t.Error(err) 6055 return 6056 } 6057 defer func(nc net.Conn) { 6058 _ = nc.Close() 6059 }(nc) 6060 _, _ = nc.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok")) 6061 _, _ = nc.Write([]byte("HTTP/1.1 408 bye\r\n")) // changing 408 to 409 makes test fail 6062 })) 6063 defer cst.close() 6064 req, err := NewRequest("GET", cst.ts.URL, nil) 6065 if err != nil { 6066 t.Fatal(err) 6067 } 6068 res, err := cst.c.Do(req) 6069 if err != nil { 6070 t.Fatal(err) 6071 } 6072 slurp, err := io.ReadAll(res.Body) 6073 if err != nil { 6074 t.Fatal(err) 6075 } 6076 if err != nil { 6077 t.Fatal(err) 6078 } 6079 if string(slurp) != "ok" { 6080 t.Fatalf("got %q; want ok", slurp) 6081 } 6082 6083 t0 := time.Now() 6084 for i := 0; i < 50; i++ { 6085 time.Sleep(time.Duration(i) * 5 * time.Millisecond) 6086 if cst.tr.IdleConnKeyCountForTesting() == 0 { 6087 if got := logout.String(); got != "" { 6088 t.Fatalf("expected no log output; got: %s", got) 6089 } 6090 return 6091 } 6092 } 6093 t.Fatalf("timeout after %v waiting for Transport connections to die off", time.Since(t0)) 6094 } 6095 6096 func TestInvalidHeaderResponse(t *testing.T) { 6097 setParallel(t) 6098 defer afterTest(t) 6099 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 6100 conn, buf, _ := w.(Hijacker).Hijack() 6101 _, _ = buf.Write([]byte("HTTP/1.1 200 OK\r\n" + 6102 "Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" + 6103 "Content-Type: text/html; charset=utf-8\r\n" + 6104 "Content-Length: 0\r\n" + 6105 "Foo : bar\r\n\r\n")) 6106 _ = buf.Flush() 6107 _ = conn.Close() 6108 })) 6109 defer cst.close() 6110 res, err := cst.c.Get(cst.ts.URL) 6111 if err != nil { 6112 t.Fatal(err) 6113 } 6114 defer func(Body io.ReadCloser) { 6115 _ = Body.Close() 6116 }(res.Body) 6117 if v := res.Header.Get("Foo"); v != "" { 6118 t.Errorf(`unexpected "Foo" header: %q`, v) 6119 } 6120 if v := res.Header.Get("Foo "); v != "bar" { 6121 t.Errorf(`bad "Foo " header value: %q, want %q`, v, "bar") 6122 } 6123 } 6124 6125 type bodyCloser bool 6126 6127 func (bc *bodyCloser) Close() error { 6128 *bc = true 6129 return nil 6130 } 6131 6132 //goland:noinspection GoUnusedParameter 6133 func (bc *bodyCloser) Read(b []byte) (n int, err error) { 6134 return 0, io.EOF 6135 } 6136 6137 // Issue 35015: ensure that Transport closes the body on any error 6138 // with an invalid request, as promised by Client.Do docs. 6139 func TestTransportClosesBodyOnInvalidRequests(t *testing.T) { 6140 cst := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 6141 t.Errorf("Should not have been invoked") 6142 })) 6143 defer cst.Close() 6144 6145 u, _ := url.Parse(cst.URL) 6146 6147 tests := []struct { 6148 name string 6149 req *Request 6150 wantErr string 6151 }{ 6152 { 6153 name: "invalid method", 6154 req: &Request{ 6155 Method: " ", 6156 URL: u, 6157 }, 6158 wantErr: "invalid method", 6159 }, 6160 { 6161 name: "nil URL", 6162 req: &Request{ 6163 Method: "GET", 6164 }, 6165 wantErr: "nil Request.URL", 6166 }, 6167 { 6168 name: "invalid header key", 6169 req: &Request{ 6170 Method: "GET", 6171 Header: Header{"💡": {"emoji"}}, 6172 URL: u, 6173 }, 6174 wantErr: "invalid header field name", 6175 }, 6176 { 6177 name: "invalid header value", 6178 req: &Request{ 6179 Method: "POST", 6180 Header: Header{"key": {"\x19"}}, 6181 URL: u, 6182 }, 6183 wantErr: "invalid header field value", 6184 }, 6185 { 6186 name: "non HTTP(s) scheme", 6187 req: &Request{ 6188 Method: "POST", 6189 URL: &url.URL{Scheme: "faux"}, 6190 }, 6191 wantErr: "unsupported protocol scheme", 6192 }, 6193 { 6194 name: "no Host in URL", 6195 req: &Request{ 6196 Method: "POST", 6197 URL: &url.URL{Scheme: "http"}, 6198 }, 6199 wantErr: "no Host", 6200 }, 6201 } 6202 6203 for _, tt := range tests { 6204 t.Run(tt.name, func(t *testing.T) { 6205 var bc bodyCloser 6206 req := tt.req 6207 req.Body = &bc 6208 _, err := DefaultClient.Do(tt.req) 6209 if err == nil { 6210 t.Fatal("Expected an error") 6211 } 6212 if !bc { 6213 t.Fatal("Expected body to have been closed") 6214 } 6215 if g, w := err.Error(), tt.wantErr; !strings.Contains(g, w) { 6216 t.Fatalf("Error mismatch\n\t%q\ndoes not contain\n\t%q", g, w) 6217 } 6218 }) 6219 } 6220 } 6221 6222 // breakableConn is a net.Conn wrapper with a Write method 6223 // that will fail when its brokenState is true. 6224 type breakableConn struct { 6225 net.Conn 6226 *brokenState 6227 } 6228 6229 type brokenState struct { 6230 sync.Mutex 6231 broken bool 6232 } 6233 6234 func (w *breakableConn) Write(b []byte) (n int, err error) { 6235 w.Lock() 6236 defer w.Unlock() 6237 if w.broken { 6238 return 0, errors.New("some write error") 6239 } 6240 return w.Conn.Write(b) 6241 } 6242 6243 // Issue 34978: don't cache a broken HTTP/2 connection 6244 func TestDontCacheBrokenHTTP2Conn(t *testing.T) { 6245 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), optQuietLog) 6246 defer cst.close() 6247 6248 var brokenState brokenState 6249 6250 const numReqs = 5 6251 var numDials, gotConns uint32 // atomic 6252 6253 cst.tr.Dial = func(netw, addr string) (net.Conn, error) { 6254 atomic.AddUint32(&numDials, 1) 6255 c, err := net.Dial(netw, addr) 6256 if err != nil { 6257 t.Errorf("unexpected Dial error: %v", err) 6258 return nil, err 6259 } 6260 return &breakableConn{c, &brokenState}, err 6261 } 6262 6263 for i := 1; i <= numReqs; i++ { 6264 brokenState.Lock() 6265 brokenState.broken = false 6266 brokenState.Unlock() 6267 6268 // doBreak controls whether we break the TCP connection after the TLS 6269 // handshake (before the HTTP/2 handshake). We test a few failures 6270 // in a row followed by a final success. 6271 doBreak := i != numReqs 6272 6273 ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 6274 GotConn: func(info httptrace.GotConnInfo) { 6275 t.Logf("got conn: %v, reused=%v, wasIdle=%v, idleTime=%v", info.Conn.LocalAddr(), info.Reused, info.WasIdle, info.IdleTime) 6276 atomic.AddUint32(&gotConns, 1) 6277 }, 6278 TLSHandshakeDone: func(cfg tls.ConnectionState, err error) { 6279 brokenState.Lock() 6280 defer brokenState.Unlock() 6281 if doBreak { 6282 brokenState.broken = true 6283 } 6284 }, 6285 }) 6286 req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil) 6287 if err != nil { 6288 t.Fatal(err) 6289 } 6290 _, err = cst.c.Do(req) 6291 if doBreak != (err != nil) { 6292 t.Errorf("for iteration %d, doBreak=%v; unexpected error %v", i, doBreak, err) 6293 } 6294 } 6295 if got, want := atomic.LoadUint32(&gotConns), 1; int(got) != want { 6296 t.Errorf("GotConn calls = %v; want %v", got, want) 6297 } 6298 if got, want := atomic.LoadUint32(&numDials), numReqs; int(got) != want { 6299 t.Errorf("Dials = %v; want %v", got, want) 6300 } 6301 } 6302 6303 // Issue 34941 6304 // When the client has too many concurrent requests on a single connection, 6305 // http.http2noCachedConnError is reported on multiple requests. There should 6306 // only be one decrement regardless of the number of failures. 6307 func TestTransportDecrementConnWhenIdleConnRemoved(t *testing.T) { 6308 defer afterTest(t) 6309 CondSkipHTTP2(t) 6310 6311 h := HandlerFunc(func(w ResponseWriter, r *Request) { 6312 _, err := w.Write([]byte("foo")) 6313 if err != nil { 6314 t.Fatalf("Write: %v", err) 6315 } 6316 }) 6317 6318 ts := httptest.NewUnstartedServer(h) 6319 ts.EnableHTTP2 = true 6320 ts.StartTLS() 6321 defer ts.Close() 6322 6323 c := ts.Client() 6324 tr := c.Transport.(*Transport) 6325 tr.MaxConnsPerHost = 1 6326 if err := ExportHttp2ConfigureTransport(tr); err != nil { 6327 t.Fatalf("ExportHttp2ConfigureTransport: %v", err) 6328 } 6329 6330 errCh := make(chan error, 300) 6331 doReq := func() { 6332 resp, err := c.Get(ts.URL) 6333 if err != nil { 6334 errCh <- fmt.Errorf("request failed: %v", err) 6335 return 6336 } 6337 defer func(Body io.ReadCloser) { 6338 _ = Body.Close() 6339 }(resp.Body) 6340 _, err = io.ReadAll(resp.Body) 6341 if err != nil { 6342 errCh <- fmt.Errorf("read body failed: %v", err) 6343 } 6344 } 6345 6346 var wg sync.WaitGroup 6347 for i := 0; i < 300; i++ { 6348 wg.Add(1) 6349 go func() { 6350 defer wg.Done() 6351 doReq() 6352 }() 6353 } 6354 wg.Wait() 6355 close(errCh) 6356 6357 for err := range errCh { 6358 t.Errorf("error occurred: %v", err) 6359 } 6360 } 6361 6362 // Issue 36820 6363 // Test that we use the older backward compatible cancellation protocol 6364 // when a RoundTripper is registered via RegisterProtocol. 6365 func TestAltProtoCancellation(t *testing.T) { 6366 defer afterTest(t) 6367 tr := &Transport{} 6368 c := &Client{ 6369 Transport: tr, 6370 Timeout: time.Millisecond, 6371 } 6372 tr.RegisterProtocol("timeout", timeoutProto{}) 6373 _, err := c.Get("timeout://bar.com/path") 6374 if err == nil { 6375 t.Error("request unexpectedly succeeded") 6376 } else if !strings.Contains(err.Error(), timeoutProtoErr.Error()) { 6377 t.Errorf("got error %q, does not contain expected string %q", err, timeoutProtoErr) 6378 } 6379 } 6380 6381 var timeoutProtoErr = errors.New("canceled as expected") 6382 6383 type timeoutProto struct{} 6384 6385 func (timeoutProto) RoundTrip(req *Request) (*Response, error) { 6386 select { 6387 case <-req.Cancel: 6388 return nil, timeoutProtoErr 6389 case <-time.After(5 * time.Second): 6390 return nil, errors.New("request was not canceled") 6391 } 6392 } 6393 6394 type roundTripFunc func(r *Request) (*Response, error) 6395 6396 func (f roundTripFunc) RoundTrip(r *Request) (*Response, error) { return f(r) } 6397 6398 // Issue 32441: body is not reset after ErrSkipAltProtocol 6399 func TestIssue32441(t *testing.T) { 6400 defer afterTest(t) 6401 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 6402 if n, _ := io.Copy(io.Discard, r.Body); n == 0 { 6403 t.Error("body length is zero") 6404 } 6405 })) 6406 defer ts.Close() 6407 c := ts.Client() 6408 c.Transport.(*Transport).RegisterProtocol("http", roundTripFunc(func(r *Request) (*Response, error) { 6409 // Draining body to trigger failure condition on actual request to server. 6410 if n, _ := io.Copy(io.Discard, r.Body); n == 0 { 6411 t.Error("body length is zero during round trip") 6412 } 6413 return nil, ErrSkipAltProtocol 6414 })) 6415 if _, err := c.Post(ts.URL, "application/octet-stream", bytes.NewBufferString("data")); err != nil { 6416 t.Error(err) 6417 } 6418 } 6419 6420 // Issue 39017. Ensure that HTTP/1 transports reject Content-Length headers 6421 // that contain a sign (eg. "+3"), per RFC 2616, Section 14.13. 6422 func TestTransportRejectsSignInContentLength(t *testing.T) { 6423 cst := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 6424 w.Header().Set("Content-Length", "+3") 6425 _, _ = w.Write([]byte("abc")) 6426 })) 6427 defer cst.Close() 6428 6429 c := cst.Client() 6430 res, err := c.Get(cst.URL) 6431 if err == nil || res != nil { 6432 t.Fatal("Expected a non-nil error and a nil http.Response") 6433 } 6434 if got, want := err.Error(), `bad Content-Length "+3"`; !strings.Contains(got, want) { 6435 t.Fatalf("Error mismatch\nGot: %q\nWanted substring: %q", got, want) 6436 } 6437 } 6438 6439 // dumpConn is a net.Conn which writes to Writer and reads from Reader 6440 type dumpConn struct { 6441 io.Writer 6442 io.Reader 6443 } 6444 6445 func (c *dumpConn) Close() error { return nil } 6446 func (c *dumpConn) LocalAddr() net.Addr { return nil } 6447 func (c *dumpConn) RemoteAddr() net.Addr { return nil } 6448 6449 //goland:noinspection GoUnusedParameter 6450 func (c *dumpConn) SetDeadline(t time.Time) error { return nil } 6451 6452 //goland:noinspection GoUnusedParameter 6453 func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil } 6454 6455 //goland:noinspection GoUnusedParameter 6456 func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil } 6457 6458 // delegateReader is a reader that delegates to another reader, 6459 // once it arrives on a channel. 6460 type delegateReader struct { 6461 c chan io.Reader 6462 r io.Reader // nil until received from c 6463 } 6464 6465 func (r *delegateReader) Read(p []byte) (int, error) { 6466 if r.r == nil { 6467 var ok bool 6468 if r.r, ok = <-r.c; !ok { 6469 return 0, errors.New("delegate closed") 6470 } 6471 } 6472 return r.r.Read(p) 6473 } 6474 6475 func testTransportRace(req *Request) { 6476 save := req.Body 6477 pr, pw := io.Pipe() 6478 defer func(pr *io.PipeReader) { 6479 _ = pr.Close() 6480 }(pr) 6481 defer func(pw *io.PipeWriter) { 6482 _ = pw.Close() 6483 }(pw) 6484 dr := &delegateReader{c: make(chan io.Reader)} 6485 6486 t := &Transport{ 6487 Dial: func(net, addr string) (net.Conn, error) { 6488 return &dumpConn{pw, dr}, nil 6489 }, 6490 } 6491 defer t.CloseIdleConnections() 6492 6493 quitReadCh := make(chan struct{}) 6494 // Wait for the request before replying with a dummy response: 6495 go func() { 6496 defer close(quitReadCh) 6497 6498 req, err := ReadRequest(bufio.NewReader(pr)) 6499 if err == nil { 6500 // Ensure all the body is read; otherwise 6501 // we'll get a partial dump. 6502 _, _ = io.Copy(io.Discard, req.Body) 6503 _ = req.Body.Close() 6504 } 6505 select { 6506 case dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n"): 6507 case quitReadCh <- struct{}{}: 6508 // Ensure delegate is closed so Read doesn't block forever. 6509 close(dr.c) 6510 } 6511 }() 6512 6513 _, _ = t.RoundTrip(req) 6514 6515 // Ensure the reader returns before we reset req.Body to prevent 6516 // a data race on req.Body. 6517 _ = pw.Close() 6518 <-quitReadCh 6519 6520 req.Body = save 6521 } 6522 6523 // Issue 37669 6524 // Test that a cancellation doesn't result in a data race due to the writeLoop 6525 // goroutine being left running, if the caller mutates the processed Request 6526 // upon completion. 6527 func TestErrorWriteLoopRace(t *testing.T) { 6528 if testing.Short() { 6529 return 6530 } 6531 t.Parallel() 6532 for i := 0; i < 1000; i++ { 6533 delay := time.Duration(mrand.Intn(5)) * time.Millisecond 6534 ctx, cancel := context.WithTimeout(context.Background(), delay) 6535 //goland:noinspection GoDeferInLoop 6536 defer cancel() 6537 6538 r := bytes.NewBuffer(make([]byte, 10000)) 6539 //goland:noinspection HttpUrlsUsage 6540 req, err := NewRequestWithContext(ctx, MethodPost, "http://example.com", r) 6541 if err != nil { 6542 t.Fatal(err) 6543 } 6544 6545 testTransportRace(req) 6546 } 6547 } 6548 6549 // Issue 41600 6550 // Test that a new request which uses the connection of an active request 6551 // cannot cause it to be canceled as well. 6552 func TestCancelRequestWhenSharingConnection(t *testing.T) { 6553 reqc := make(chan chan struct{}, 2) 6554 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) { 6555 ch := make(chan struct{}, 1) 6556 reqc <- ch 6557 <-ch 6558 w.Header().Add("Content-Length", "0") 6559 })) 6560 defer ts.Close() 6561 6562 client := ts.Client() 6563 transport := client.Transport.(*Transport) 6564 transport.MaxIdleConns = 1 6565 transport.MaxConnsPerHost = 1 6566 6567 var wg sync.WaitGroup 6568 6569 wg.Add(1) 6570 putidlec := make(chan chan struct{}) 6571 go func() { 6572 defer wg.Done() 6573 ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 6574 PutIdleConn: func(error) { 6575 // Signal that the idle conn has been returned to the pool, 6576 // and wait for the order to proceed. 6577 ch := make(chan struct{}) 6578 putidlec <- ch 6579 <-ch 6580 }, 6581 }) 6582 req, _ := NewRequestWithContext(ctx, "GET", ts.URL, nil) 6583 res, err := client.Do(req) 6584 if err == nil { 6585 _ = res.Body.Close() 6586 } 6587 if err != nil { 6588 t.Errorf("request 1: got err %v, want nil", err) 6589 } 6590 }() 6591 6592 // Wait for the first request to receive a response and return the 6593 // connection to the idle pool. 6594 r1c := <-reqc 6595 close(r1c) 6596 idlec := <-putidlec 6597 6598 wg.Add(1) 6599 cancelctx, cancel := context.WithCancel(context.Background()) 6600 go func() { 6601 defer wg.Done() 6602 req, _ := NewRequestWithContext(cancelctx, "GET", ts.URL, nil) 6603 res, err := client.Do(req) 6604 if err == nil { 6605 _ = res.Body.Close() 6606 } 6607 if !errors.Is(err, context.Canceled) { 6608 t.Errorf("request 2: got err %v, want Canceled", err) 6609 } 6610 }() 6611 6612 // Wait for the second request to arrive at the server, and then cancel 6613 // the request context. 6614 r2c := <-reqc 6615 cancel() 6616 6617 // Give the cancelation a moment to take effect, and then unblock the first request. 6618 time.Sleep(1 * time.Millisecond) 6619 close(idlec) 6620 6621 close(r2c) 6622 wg.Wait() 6623 }