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