github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/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 "errors" 20 "fmt" 21 "internal/nettrace" 22 "internal/testenv" 23 "io" 24 "io/ioutil" 25 "log" 26 "net" 27 . "net/http" 28 "net/http/httptest" 29 "net/http/httptrace" 30 "net/http/httputil" 31 "net/http/internal" 32 "net/url" 33 "os" 34 "reflect" 35 "runtime" 36 "strconv" 37 "strings" 38 "sync" 39 "testing" 40 "time" 41 ) 42 43 // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close 44 // and then verify that the final 2 responses get errors back. 45 46 // hostPortHandler writes back the client's "host:port". 47 var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 48 if r.FormValue("close") == "true" { 49 w.Header().Set("Connection", "close") 50 } 51 w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close)) 52 w.Write([]byte(r.RemoteAddr)) 53 }) 54 55 // testCloseConn is a net.Conn tracked by a testConnSet. 56 type testCloseConn struct { 57 net.Conn 58 set *testConnSet 59 } 60 61 func (c *testCloseConn) Close() error { 62 c.set.remove(c) 63 return c.Conn.Close() 64 } 65 66 // testConnSet tracks a set of TCP connections and whether they've 67 // been closed. 68 type testConnSet struct { 69 t *testing.T 70 mu sync.Mutex // guards closed and list 71 closed map[net.Conn]bool 72 list []net.Conn // in order created 73 } 74 75 func (tcs *testConnSet) insert(c net.Conn) { 76 tcs.mu.Lock() 77 defer tcs.mu.Unlock() 78 tcs.closed[c] = false 79 tcs.list = append(tcs.list, c) 80 } 81 82 func (tcs *testConnSet) remove(c net.Conn) { 83 tcs.mu.Lock() 84 defer tcs.mu.Unlock() 85 tcs.closed[c] = true 86 } 87 88 // some tests use this to manage raw tcp connections for later inspection 89 func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) { 90 connSet := &testConnSet{ 91 t: t, 92 closed: make(map[net.Conn]bool), 93 } 94 dial := func(n, addr string) (net.Conn, error) { 95 c, err := net.Dial(n, addr) 96 if err != nil { 97 return nil, err 98 } 99 tc := &testCloseConn{c, connSet} 100 connSet.insert(tc) 101 return tc, nil 102 } 103 return connSet, dial 104 } 105 106 func (tcs *testConnSet) check(t *testing.T) { 107 tcs.mu.Lock() 108 defer tcs.mu.Unlock() 109 for i := 4; i >= 0; i-- { 110 for i, c := range tcs.list { 111 if tcs.closed[c] { 112 continue 113 } 114 if i != 0 { 115 tcs.mu.Unlock() 116 time.Sleep(50 * time.Millisecond) 117 tcs.mu.Lock() 118 continue 119 } 120 t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list)) 121 } 122 } 123 } 124 125 // Two subsequent requests and verify their response is the same. 126 // The response from the server is our own IP:port 127 func TestTransportKeepAlives(t *testing.T) { 128 defer afterTest(t) 129 ts := httptest.NewServer(hostPortHandler) 130 defer ts.Close() 131 132 for _, disableKeepAlive := range []bool{false, true} { 133 tr := &Transport{DisableKeepAlives: disableKeepAlive} 134 defer tr.CloseIdleConnections() 135 c := &Client{Transport: tr} 136 137 fetch := func(n int) string { 138 res, err := c.Get(ts.URL) 139 if err != nil { 140 t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err) 141 } 142 body, err := ioutil.ReadAll(res.Body) 143 if err != nil { 144 t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err) 145 } 146 return string(body) 147 } 148 149 body1 := fetch(1) 150 body2 := fetch(2) 151 152 bodiesDiffer := body1 != body2 153 if bodiesDiffer != disableKeepAlive { 154 t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 155 disableKeepAlive, bodiesDiffer, body1, body2) 156 } 157 } 158 } 159 160 func TestTransportConnectionCloseOnResponse(t *testing.T) { 161 defer afterTest(t) 162 ts := httptest.NewServer(hostPortHandler) 163 defer ts.Close() 164 165 connSet, testDial := makeTestDial(t) 166 167 for _, connectionClose := range []bool{false, true} { 168 tr := &Transport{ 169 Dial: testDial, 170 } 171 c := &Client{Transport: tr} 172 173 fetch := func(n int) string { 174 req := new(Request) 175 var err error 176 req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose)) 177 if err != nil { 178 t.Fatalf("URL parse error: %v", err) 179 } 180 req.Method = "GET" 181 req.Proto = "HTTP/1.1" 182 req.ProtoMajor = 1 183 req.ProtoMinor = 1 184 185 res, err := c.Do(req) 186 if err != nil { 187 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) 188 } 189 defer res.Body.Close() 190 body, err := ioutil.ReadAll(res.Body) 191 if err != nil { 192 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) 193 } 194 return string(body) 195 } 196 197 body1 := fetch(1) 198 body2 := fetch(2) 199 bodiesDiffer := body1 != body2 200 if bodiesDiffer != connectionClose { 201 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 202 connectionClose, bodiesDiffer, body1, body2) 203 } 204 205 tr.CloseIdleConnections() 206 } 207 208 connSet.check(t) 209 } 210 211 func TestTransportConnectionCloseOnRequest(t *testing.T) { 212 defer afterTest(t) 213 ts := httptest.NewServer(hostPortHandler) 214 defer ts.Close() 215 216 connSet, testDial := makeTestDial(t) 217 218 for _, connectionClose := range []bool{false, true} { 219 tr := &Transport{ 220 Dial: testDial, 221 } 222 c := &Client{Transport: tr} 223 224 fetch := func(n int) string { 225 req := new(Request) 226 var err error 227 req.URL, err = url.Parse(ts.URL) 228 if err != nil { 229 t.Fatalf("URL parse error: %v", err) 230 } 231 req.Method = "GET" 232 req.Proto = "HTTP/1.1" 233 req.ProtoMajor = 1 234 req.ProtoMinor = 1 235 req.Close = connectionClose 236 237 res, err := c.Do(req) 238 if err != nil { 239 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) 240 } 241 if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(connectionClose); got != want { 242 t.Errorf("For connectionClose = %v; handler's X-Saw-Close was %v; want %v", 243 connectionClose, got, !connectionClose) 244 } 245 body, err := ioutil.ReadAll(res.Body) 246 if err != nil { 247 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) 248 } 249 return string(body) 250 } 251 252 body1 := fetch(1) 253 body2 := fetch(2) 254 bodiesDiffer := body1 != body2 255 if bodiesDiffer != connectionClose { 256 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 257 connectionClose, bodiesDiffer, body1, body2) 258 } 259 260 tr.CloseIdleConnections() 261 } 262 263 connSet.check(t) 264 } 265 266 // if the Transport's DisableKeepAlives is set, all requests should 267 // send Connection: close. 268 // HTTP/1-only (Connection: close doesn't exist in h2) 269 func TestTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T) { 270 defer afterTest(t) 271 ts := httptest.NewServer(hostPortHandler) 272 defer ts.Close() 273 274 tr := &Transport{ 275 DisableKeepAlives: true, 276 } 277 c := &Client{Transport: tr} 278 res, err := c.Get(ts.URL) 279 if err != nil { 280 t.Fatal(err) 281 } 282 res.Body.Close() 283 if res.Header.Get("X-Saw-Close") != "true" { 284 t.Errorf("handler didn't see Connection: close ") 285 } 286 } 287 288 func TestTransportIdleCacheKeys(t *testing.T) { 289 defer afterTest(t) 290 ts := httptest.NewServer(hostPortHandler) 291 defer ts.Close() 292 293 tr := &Transport{DisableKeepAlives: false} 294 c := &Client{Transport: tr} 295 296 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 297 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) 298 } 299 300 resp, err := c.Get(ts.URL) 301 if err != nil { 302 t.Error(err) 303 } 304 ioutil.ReadAll(resp.Body) 305 306 keys := tr.IdleConnKeysForTesting() 307 if e, g := 1, len(keys); e != g { 308 t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g) 309 } 310 311 if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e { 312 t.Errorf("Expected idle cache key %q; got %q", e, keys[0]) 313 } 314 315 tr.CloseIdleConnections() 316 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 317 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) 318 } 319 } 320 321 // Tests that the HTTP transport re-uses connections when a client 322 // reads to the end of a response Body without closing it. 323 func TestTransportReadToEndReusesConn(t *testing.T) { 324 defer afterTest(t) 325 const msg = "foobar" 326 327 var addrSeen map[string]int 328 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 329 addrSeen[r.RemoteAddr]++ 330 if r.URL.Path == "/chunked/" { 331 w.WriteHeader(200) 332 w.(Flusher).Flush() 333 } else { 334 w.Header().Set("Content-Type", strconv.Itoa(len(msg))) 335 w.WriteHeader(200) 336 } 337 w.Write([]byte(msg)) 338 })) 339 defer ts.Close() 340 341 buf := make([]byte, len(msg)) 342 343 for pi, path := range []string{"/content-length/", "/chunked/"} { 344 wantLen := []int{len(msg), -1}[pi] 345 addrSeen = make(map[string]int) 346 for i := 0; i < 3; i++ { 347 res, err := Get(ts.URL + path) 348 if err != nil { 349 t.Errorf("Get %s: %v", path, err) 350 continue 351 } 352 // We want to close this body eventually (before the 353 // defer afterTest at top runs), but not before the 354 // len(addrSeen) check at the bottom of this test, 355 // since Closing this early in the loop would risk 356 // making connections be re-used for the wrong reason. 357 defer res.Body.Close() 358 359 if res.ContentLength != int64(wantLen) { 360 t.Errorf("%s res.ContentLength = %d; want %d", path, res.ContentLength, wantLen) 361 } 362 n, err := res.Body.Read(buf) 363 if n != len(msg) || err != io.EOF { 364 t.Errorf("%s Read = %v, %v; want %d, EOF", path, n, err, len(msg)) 365 } 366 } 367 if len(addrSeen) != 1 { 368 t.Errorf("for %s, server saw %d distinct client addresses; want 1", path, len(addrSeen)) 369 } 370 } 371 } 372 373 func TestTransportMaxPerHostIdleConns(t *testing.T) { 374 defer afterTest(t) 375 resch := make(chan string) 376 gotReq := make(chan bool) 377 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 378 gotReq <- true 379 msg := <-resch 380 _, err := w.Write([]byte(msg)) 381 if err != nil { 382 t.Fatalf("Write: %v", err) 383 } 384 })) 385 defer ts.Close() 386 maxIdleConnsPerHost := 2 387 tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConnsPerHost} 388 c := &Client{Transport: tr} 389 390 // Start 3 outstanding requests and wait for the server to get them. 391 // Their responses will hang until we write to resch, though. 392 donech := make(chan bool) 393 doReq := func() { 394 resp, err := c.Get(ts.URL) 395 if err != nil { 396 t.Error(err) 397 return 398 } 399 if _, err := ioutil.ReadAll(resp.Body); err != nil { 400 t.Errorf("ReadAll: %v", err) 401 return 402 } 403 donech <- true 404 } 405 go doReq() 406 <-gotReq 407 go doReq() 408 <-gotReq 409 go doReq() 410 <-gotReq 411 412 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 413 t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g) 414 } 415 416 resch <- "res1" 417 <-donech 418 keys := tr.IdleConnKeysForTesting() 419 if e, g := 1, len(keys); e != g { 420 t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g) 421 } 422 cacheKey := "|http|" + ts.Listener.Addr().String() 423 if keys[0] != cacheKey { 424 t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0]) 425 } 426 if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g { 427 t.Errorf("after first response, expected %d idle conns; got %d", e, g) 428 } 429 430 resch <- "res2" 431 <-donech 432 if g, w := tr.IdleConnCountForTesting(cacheKey), 2; g != w { 433 t.Errorf("after second response, idle conns = %d; want %d", g, w) 434 } 435 436 resch <- "res3" 437 <-donech 438 if g, w := tr.IdleConnCountForTesting(cacheKey), maxIdleConnsPerHost; g != w { 439 t.Errorf("after third response, idle conns = %d; want %d", g, w) 440 } 441 } 442 443 func TestTransportRemovesDeadIdleConnections(t *testing.T) { 444 if runtime.GOOS == "plan9" { 445 t.Skip("skipping test; see https://golang.org/issue/15464") 446 } 447 defer afterTest(t) 448 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 449 io.WriteString(w, r.RemoteAddr) 450 })) 451 defer ts.Close() 452 453 tr := &Transport{} 454 defer tr.CloseIdleConnections() 455 c := &Client{Transport: tr} 456 457 doReq := func(name string) string { 458 // Do a POST instead of a GET to prevent the Transport's 459 // idempotent request retry logic from kicking in... 460 res, err := c.Post(ts.URL, "", nil) 461 if err != nil { 462 t.Fatalf("%s: %v", name, err) 463 } 464 if res.StatusCode != 200 { 465 t.Fatalf("%s: %v", name, res.Status) 466 } 467 defer res.Body.Close() 468 slurp, err := ioutil.ReadAll(res.Body) 469 if err != nil { 470 t.Fatalf("%s: %v", name, err) 471 } 472 return string(slurp) 473 } 474 475 first := doReq("first") 476 keys1 := tr.IdleConnKeysForTesting() 477 478 ts.CloseClientConnections() 479 480 var keys2 []string 481 if !waitCondition(3*time.Second, 50*time.Millisecond, func() bool { 482 keys2 = tr.IdleConnKeysForTesting() 483 return len(keys2) == 0 484 }) { 485 t.Fatalf("Transport didn't notice idle connection's death.\nbefore: %q\n after: %q\n", keys1, keys2) 486 } 487 488 second := doReq("second") 489 if first == second { 490 t.Errorf("expected a different connection between requests. got %q both times", first) 491 } 492 } 493 494 func TestTransportServerClosingUnexpectedly(t *testing.T) { 495 setParallel(t) 496 defer afterTest(t) 497 ts := httptest.NewServer(hostPortHandler) 498 defer ts.Close() 499 500 tr := &Transport{} 501 c := &Client{Transport: tr} 502 503 fetch := func(n, retries int) string { 504 condFatalf := func(format string, arg ...interface{}) { 505 if retries <= 0 { 506 t.Fatalf(format, arg...) 507 } 508 t.Logf("retrying shortly after expected error: "+format, arg...) 509 time.Sleep(time.Second / time.Duration(retries)) 510 } 511 for retries >= 0 { 512 retries-- 513 res, err := c.Get(ts.URL) 514 if err != nil { 515 condFatalf("error in req #%d, GET: %v", n, err) 516 continue 517 } 518 body, err := ioutil.ReadAll(res.Body) 519 if err != nil { 520 condFatalf("error in req #%d, ReadAll: %v", n, err) 521 continue 522 } 523 res.Body.Close() 524 return string(body) 525 } 526 panic("unreachable") 527 } 528 529 body1 := fetch(1, 0) 530 body2 := fetch(2, 0) 531 532 ts.CloseClientConnections() // surprise! 533 534 // This test has an expected race. Sleeping for 25 ms prevents 535 // it on most fast machines, causing the next fetch() call to 536 // succeed quickly. But if we do get errors, fetch() will retry 5 537 // times with some delays between. 538 time.Sleep(25 * time.Millisecond) 539 540 body3 := fetch(3, 5) 541 542 if body1 != body2 { 543 t.Errorf("expected body1 and body2 to be equal") 544 } 545 if body2 == body3 { 546 t.Errorf("expected body2 and body3 to be different") 547 } 548 } 549 550 // Test for https://golang.org/issue/2616 (appropriate issue number) 551 // This fails pretty reliably with GOMAXPROCS=100 or something high. 552 func TestStressSurpriseServerCloses(t *testing.T) { 553 defer afterTest(t) 554 if testing.Short() { 555 t.Skip("skipping test in short mode") 556 } 557 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 558 w.Header().Set("Content-Length", "5") 559 w.Header().Set("Content-Type", "text/plain") 560 w.Write([]byte("Hello")) 561 w.(Flusher).Flush() 562 conn, buf, _ := w.(Hijacker).Hijack() 563 buf.Flush() 564 conn.Close() 565 })) 566 defer ts.Close() 567 568 tr := &Transport{DisableKeepAlives: false} 569 c := &Client{Transport: tr} 570 defer tr.CloseIdleConnections() 571 572 // Do a bunch of traffic from different goroutines. Send to activityc 573 // after each request completes, regardless of whether it failed. 574 // If these are too high, OS X exhausts its ephemeral ports 575 // and hangs waiting for them to transition TCP states. That's 576 // not what we want to test. TODO(bradfitz): use an io.Pipe 577 // dialer for this test instead? 578 const ( 579 numClients = 20 580 reqsPerClient = 25 581 ) 582 activityc := make(chan bool) 583 for i := 0; i < numClients; i++ { 584 go func() { 585 for i := 0; i < reqsPerClient; i++ { 586 res, err := c.Get(ts.URL) 587 if err == nil { 588 // We expect errors since the server is 589 // hanging up on us after telling us to 590 // send more requests, so we don't 591 // actually care what the error is. 592 // But we want to close the body in cases 593 // where we won the race. 594 res.Body.Close() 595 } 596 activityc <- true 597 } 598 }() 599 } 600 601 // Make sure all the request come back, one way or another. 602 for i := 0; i < numClients*reqsPerClient; i++ { 603 select { 604 case <-activityc: 605 case <-time.After(5 * time.Second): 606 t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile") 607 } 608 } 609 } 610 611 // TestTransportHeadResponses verifies that we deal with Content-Lengths 612 // with no bodies properly 613 func TestTransportHeadResponses(t *testing.T) { 614 defer afterTest(t) 615 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 616 if r.Method != "HEAD" { 617 panic("expected HEAD; got " + r.Method) 618 } 619 w.Header().Set("Content-Length", "123") 620 w.WriteHeader(200) 621 })) 622 defer ts.Close() 623 624 tr := &Transport{DisableKeepAlives: false} 625 c := &Client{Transport: tr} 626 for i := 0; i < 2; i++ { 627 res, err := c.Head(ts.URL) 628 if err != nil { 629 t.Errorf("error on loop %d: %v", i, err) 630 continue 631 } 632 if e, g := "123", res.Header.Get("Content-Length"); e != g { 633 t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g) 634 } 635 if e, g := int64(123), res.ContentLength; e != g { 636 t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g) 637 } 638 if all, err := ioutil.ReadAll(res.Body); err != nil { 639 t.Errorf("loop %d: Body ReadAll: %v", i, err) 640 } else if len(all) != 0 { 641 t.Errorf("Bogus body %q", all) 642 } 643 } 644 } 645 646 // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding 647 // on responses to HEAD requests. 648 func TestTransportHeadChunkedResponse(t *testing.T) { 649 defer afterTest(t) 650 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 651 if r.Method != "HEAD" { 652 panic("expected HEAD; got " + r.Method) 653 } 654 w.Header().Set("Transfer-Encoding", "chunked") // client should ignore 655 w.Header().Set("x-client-ipport", r.RemoteAddr) 656 w.WriteHeader(200) 657 })) 658 defer ts.Close() 659 660 tr := &Transport{DisableKeepAlives: false} 661 c := &Client{Transport: tr} 662 defer tr.CloseIdleConnections() 663 664 // Ensure that we wait for the readLoop to complete before 665 // calling Head again 666 didRead := make(chan bool) 667 SetReadLoopBeforeNextReadHook(func() { didRead <- true }) 668 defer SetReadLoopBeforeNextReadHook(nil) 669 670 res1, err := c.Head(ts.URL) 671 <-didRead 672 673 if err != nil { 674 t.Fatalf("request 1 error: %v", err) 675 } 676 677 res2, err := c.Head(ts.URL) 678 <-didRead 679 680 if err != nil { 681 t.Fatalf("request 2 error: %v", err) 682 } 683 if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 { 684 t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2) 685 } 686 } 687 688 var roundTripTests = []struct { 689 accept string 690 expectAccept string 691 compressed bool 692 }{ 693 // Requests with no accept-encoding header use transparent compression 694 {"", "gzip", false}, 695 // Requests with other accept-encoding should pass through unmodified 696 {"foo", "foo", false}, 697 // Requests with accept-encoding == gzip should be passed through 698 {"gzip", "gzip", true}, 699 } 700 701 // Test that the modification made to the Request by the RoundTripper is cleaned up 702 func TestRoundTripGzip(t *testing.T) { 703 defer afterTest(t) 704 const responseBody = "test response body" 705 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 706 accept := req.Header.Get("Accept-Encoding") 707 if expect := req.FormValue("expect_accept"); accept != expect { 708 t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q", 709 req.FormValue("testnum"), accept, expect) 710 } 711 if accept == "gzip" { 712 rw.Header().Set("Content-Encoding", "gzip") 713 gz := gzip.NewWriter(rw) 714 gz.Write([]byte(responseBody)) 715 gz.Close() 716 } else { 717 rw.Header().Set("Content-Encoding", accept) 718 rw.Write([]byte(responseBody)) 719 } 720 })) 721 defer ts.Close() 722 723 for i, test := range roundTripTests { 724 // Test basic request (no accept-encoding) 725 req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil) 726 if test.accept != "" { 727 req.Header.Set("Accept-Encoding", test.accept) 728 } 729 res, err := DefaultTransport.RoundTrip(req) 730 var body []byte 731 if test.compressed { 732 var r *gzip.Reader 733 r, err = gzip.NewReader(res.Body) 734 if err != nil { 735 t.Errorf("%d. gzip NewReader: %v", i, err) 736 continue 737 } 738 body, err = ioutil.ReadAll(r) 739 res.Body.Close() 740 } else { 741 body, err = ioutil.ReadAll(res.Body) 742 } 743 if err != nil { 744 t.Errorf("%d. Error: %q", i, err) 745 continue 746 } 747 if g, e := string(body), responseBody; g != e { 748 t.Errorf("%d. body = %q; want %q", i, g, e) 749 } 750 if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e { 751 t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e) 752 } 753 if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e { 754 t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e) 755 } 756 } 757 758 } 759 760 func TestTransportGzip(t *testing.T) { 761 defer afterTest(t) 762 const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 763 const nRandBytes = 1024 * 1024 764 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 765 if req.Method == "HEAD" { 766 if g := req.Header.Get("Accept-Encoding"); g != "" { 767 t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g) 768 } 769 return 770 } 771 if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e { 772 t.Errorf("Accept-Encoding = %q, want %q", g, e) 773 } 774 rw.Header().Set("Content-Encoding", "gzip") 775 776 var w io.Writer = rw 777 var buf bytes.Buffer 778 if req.FormValue("chunked") == "0" { 779 w = &buf 780 defer io.Copy(rw, &buf) 781 defer func() { 782 rw.Header().Set("Content-Length", strconv.Itoa(buf.Len())) 783 }() 784 } 785 gz := gzip.NewWriter(w) 786 gz.Write([]byte(testString)) 787 if req.FormValue("body") == "large" { 788 io.CopyN(gz, rand.Reader, nRandBytes) 789 } 790 gz.Close() 791 })) 792 defer ts.Close() 793 794 for _, chunked := range []string{"1", "0"} { 795 c := &Client{Transport: &Transport{}} 796 797 // First fetch something large, but only read some of it. 798 res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked) 799 if err != nil { 800 t.Fatalf("large get: %v", err) 801 } 802 buf := make([]byte, len(testString)) 803 n, err := io.ReadFull(res.Body, buf) 804 if err != nil { 805 t.Fatalf("partial read of large response: size=%d, %v", n, err) 806 } 807 if e, g := testString, string(buf); e != g { 808 t.Errorf("partial read got %q, expected %q", g, e) 809 } 810 res.Body.Close() 811 // Read on the body, even though it's closed 812 n, err = res.Body.Read(buf) 813 if n != 0 || err == nil { 814 t.Errorf("expected error post-closed large Read; got = %d, %v", n, err) 815 } 816 817 // Then something small. 818 res, err = c.Get(ts.URL + "/?chunked=" + chunked) 819 if err != nil { 820 t.Fatal(err) 821 } 822 body, err := ioutil.ReadAll(res.Body) 823 if err != nil { 824 t.Fatal(err) 825 } 826 if g, e := string(body), testString; g != e { 827 t.Fatalf("body = %q; want %q", g, e) 828 } 829 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 830 t.Fatalf("Content-Encoding = %q; want %q", g, e) 831 } 832 833 // Read on the body after it's been fully read: 834 n, err = res.Body.Read(buf) 835 if n != 0 || err == nil { 836 t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err) 837 } 838 res.Body.Close() 839 n, err = res.Body.Read(buf) 840 if n != 0 || err == nil { 841 t.Errorf("expected Read error after Close; got %d, %v", n, err) 842 } 843 } 844 845 // And a HEAD request too, because they're always weird. 846 c := &Client{Transport: &Transport{}} 847 res, err := c.Head(ts.URL) 848 if err != nil { 849 t.Fatalf("Head: %v", err) 850 } 851 if res.StatusCode != 200 { 852 t.Errorf("Head status=%d; want=200", res.StatusCode) 853 } 854 } 855 856 // If a request has Expect:100-continue header, the request blocks sending body until the first response. 857 // Premature consumption of the request body should not be occurred. 858 func TestTransportExpect100Continue(t *testing.T) { 859 defer afterTest(t) 860 861 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 862 switch req.URL.Path { 863 case "/100": 864 // This endpoint implicitly responds 100 Continue and reads body. 865 if _, err := io.Copy(ioutil.Discard, req.Body); err != nil { 866 t.Error("Failed to read Body", err) 867 } 868 rw.WriteHeader(StatusOK) 869 case "/200": 870 // Go 1.5 adds Connection: close header if the client expect 871 // continue but not entire request body is consumed. 872 rw.WriteHeader(StatusOK) 873 case "/500": 874 rw.WriteHeader(StatusInternalServerError) 875 case "/keepalive": 876 // This hijacked endpoint responds error without Connection:close. 877 _, bufrw, err := rw.(Hijacker).Hijack() 878 if err != nil { 879 log.Fatal(err) 880 } 881 bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n") 882 bufrw.WriteString("Content-Length: 0\r\n\r\n") 883 bufrw.Flush() 884 case "/timeout": 885 // This endpoint tries to read body without 100 (Continue) response. 886 // After ExpectContinueTimeout, the reading will be started. 887 conn, bufrw, err := rw.(Hijacker).Hijack() 888 if err != nil { 889 log.Fatal(err) 890 } 891 if _, err := io.CopyN(ioutil.Discard, bufrw, req.ContentLength); err != nil { 892 t.Error("Failed to read Body", err) 893 } 894 bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n") 895 bufrw.Flush() 896 conn.Close() 897 } 898 899 })) 900 defer ts.Close() 901 902 tests := []struct { 903 path string 904 body []byte 905 sent int 906 status int 907 }{ 908 {path: "/100", body: []byte("hello"), sent: 5, status: 200}, // Got 100 followed by 200, entire body is sent. 909 {path: "/200", body: []byte("hello"), sent: 0, status: 200}, // Got 200 without 100. body isn't sent. 910 {path: "/500", body: []byte("hello"), sent: 0, status: 500}, // Got 500 without 100. body isn't sent. 911 {path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Although without Connection:close, body isn't sent. 912 {path: "/timeout", body: []byte("hello"), sent: 5, status: 200}, // Timeout exceeded and entire body is sent. 913 } 914 915 for i, v := range tests { 916 tr := &Transport{ExpectContinueTimeout: 2 * time.Second} 917 defer tr.CloseIdleConnections() 918 c := &Client{Transport: tr} 919 920 body := bytes.NewReader(v.body) 921 req, err := NewRequest("PUT", ts.URL+v.path, body) 922 if err != nil { 923 t.Fatal(err) 924 } 925 req.Header.Set("Expect", "100-continue") 926 req.ContentLength = int64(len(v.body)) 927 928 resp, err := c.Do(req) 929 if err != nil { 930 t.Fatal(err) 931 } 932 resp.Body.Close() 933 934 sent := len(v.body) - body.Len() 935 if v.status != resp.StatusCode { 936 t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path) 937 } 938 if v.sent != sent { 939 t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path) 940 } 941 } 942 } 943 944 func TestTransportProxy(t *testing.T) { 945 defer afterTest(t) 946 ch := make(chan string, 1) 947 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 948 ch <- "real server" 949 })) 950 defer ts.Close() 951 proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 952 ch <- "proxy for " + r.URL.String() 953 })) 954 defer proxy.Close() 955 956 pu, err := url.Parse(proxy.URL) 957 if err != nil { 958 t.Fatal(err) 959 } 960 c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}} 961 c.Head(ts.URL) 962 got := <-ch 963 want := "proxy for " + ts.URL + "/" 964 if got != want { 965 t.Errorf("want %q, got %q", want, got) 966 } 967 } 968 969 // TestTransportGzipRecursive sends a gzip quine and checks that the 970 // client gets the same value back. This is more cute than anything, 971 // but checks that we don't recurse forever, and checks that 972 // Content-Encoding is removed. 973 func TestTransportGzipRecursive(t *testing.T) { 974 defer afterTest(t) 975 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 976 w.Header().Set("Content-Encoding", "gzip") 977 w.Write(rgz) 978 })) 979 defer ts.Close() 980 981 tr := &Transport{} 982 defer tr.CloseIdleConnections() 983 c := &Client{Transport: tr} 984 res, err := c.Get(ts.URL) 985 if err != nil { 986 t.Fatal(err) 987 } 988 body, err := ioutil.ReadAll(res.Body) 989 if err != nil { 990 t.Fatal(err) 991 } 992 if !bytes.Equal(body, rgz) { 993 t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x", 994 body, rgz) 995 } 996 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 997 t.Fatalf("Content-Encoding = %q; want %q", g, e) 998 } 999 } 1000 1001 // golang.org/issue/7750: request fails when server replies with 1002 // a short gzip body 1003 func TestTransportGzipShort(t *testing.T) { 1004 defer afterTest(t) 1005 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1006 w.Header().Set("Content-Encoding", "gzip") 1007 w.Write([]byte{0x1f, 0x8b}) 1008 })) 1009 defer ts.Close() 1010 1011 tr := &Transport{} 1012 defer tr.CloseIdleConnections() 1013 c := &Client{Transport: tr} 1014 res, err := c.Get(ts.URL) 1015 if err != nil { 1016 t.Fatal(err) 1017 } 1018 defer res.Body.Close() 1019 _, err = ioutil.ReadAll(res.Body) 1020 if err == nil { 1021 t.Fatal("Expect an error from reading a body.") 1022 } 1023 if err != io.ErrUnexpectedEOF { 1024 t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err) 1025 } 1026 } 1027 1028 // Wait until number of goroutines is no greater than nmax, or time out. 1029 func waitNumGoroutine(nmax int) int { 1030 nfinal := runtime.NumGoroutine() 1031 for ntries := 10; ntries > 0 && nfinal > nmax; ntries-- { 1032 time.Sleep(50 * time.Millisecond) 1033 runtime.GC() 1034 nfinal = runtime.NumGoroutine() 1035 } 1036 return nfinal 1037 } 1038 1039 // tests that persistent goroutine connections shut down when no longer desired. 1040 func TestTransportPersistConnLeak(t *testing.T) { 1041 setParallel(t) 1042 defer afterTest(t) 1043 gotReqCh := make(chan bool) 1044 unblockCh := make(chan bool) 1045 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1046 gotReqCh <- true 1047 <-unblockCh 1048 w.Header().Set("Content-Length", "0") 1049 w.WriteHeader(204) 1050 })) 1051 defer ts.Close() 1052 1053 tr := &Transport{} 1054 c := &Client{Transport: tr} 1055 1056 n0 := runtime.NumGoroutine() 1057 1058 const numReq = 25 1059 didReqCh := make(chan bool) 1060 for i := 0; i < numReq; i++ { 1061 go func() { 1062 res, err := c.Get(ts.URL) 1063 didReqCh <- true 1064 if err != nil { 1065 t.Errorf("client fetch error: %v", err) 1066 return 1067 } 1068 res.Body.Close() 1069 }() 1070 } 1071 1072 // Wait for all goroutines to be stuck in the Handler. 1073 for i := 0; i < numReq; i++ { 1074 <-gotReqCh 1075 } 1076 1077 nhigh := runtime.NumGoroutine() 1078 1079 // Tell all handlers to unblock and reply. 1080 for i := 0; i < numReq; i++ { 1081 unblockCh <- true 1082 } 1083 1084 // Wait for all HTTP clients to be done. 1085 for i := 0; i < numReq; i++ { 1086 <-didReqCh 1087 } 1088 1089 tr.CloseIdleConnections() 1090 nfinal := waitNumGoroutine(n0 + 5) 1091 1092 growth := nfinal - n0 1093 1094 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 1095 // Previously we were leaking one per numReq. 1096 if int(growth) > 5 { 1097 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 1098 t.Error("too many new goroutines") 1099 } 1100 } 1101 1102 // golang.org/issue/4531: Transport leaks goroutines when 1103 // request.ContentLength is explicitly short 1104 func TestTransportPersistConnLeakShortBody(t *testing.T) { 1105 setParallel(t) 1106 defer afterTest(t) 1107 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1108 })) 1109 defer ts.Close() 1110 1111 tr := &Transport{} 1112 c := &Client{Transport: tr} 1113 1114 n0 := runtime.NumGoroutine() 1115 body := []byte("Hello") 1116 for i := 0; i < 20; i++ { 1117 req, err := NewRequest("POST", ts.URL, bytes.NewReader(body)) 1118 if err != nil { 1119 t.Fatal(err) 1120 } 1121 req.ContentLength = int64(len(body) - 2) // explicitly short 1122 _, err = c.Do(req) 1123 if err == nil { 1124 t.Fatal("Expect an error from writing too long of a body.") 1125 } 1126 } 1127 nhigh := runtime.NumGoroutine() 1128 tr.CloseIdleConnections() 1129 nfinal := waitNumGoroutine(n0 + 5) 1130 1131 growth := nfinal - n0 1132 1133 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 1134 // Previously we were leaking one per numReq. 1135 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 1136 if int(growth) > 5 { 1137 t.Error("too many new goroutines") 1138 } 1139 } 1140 1141 // This used to crash; https://golang.org/issue/3266 1142 func TestTransportIdleConnCrash(t *testing.T) { 1143 defer afterTest(t) 1144 tr := &Transport{} 1145 c := &Client{Transport: tr} 1146 1147 unblockCh := make(chan bool, 1) 1148 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1149 <-unblockCh 1150 tr.CloseIdleConnections() 1151 })) 1152 defer ts.Close() 1153 1154 didreq := make(chan bool) 1155 go func() { 1156 res, err := c.Get(ts.URL) 1157 if err != nil { 1158 t.Error(err) 1159 } else { 1160 res.Body.Close() // returns idle conn 1161 } 1162 didreq <- true 1163 }() 1164 unblockCh <- true 1165 <-didreq 1166 } 1167 1168 // Test that the transport doesn't close the TCP connection early, 1169 // before the response body has been read. This was a regression 1170 // which sadly lacked a triggering test. The large response body made 1171 // the old race easier to trigger. 1172 func TestIssue3644(t *testing.T) { 1173 defer afterTest(t) 1174 const numFoos = 5000 1175 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1176 w.Header().Set("Connection", "close") 1177 for i := 0; i < numFoos; i++ { 1178 w.Write([]byte("foo ")) 1179 } 1180 })) 1181 defer ts.Close() 1182 tr := &Transport{} 1183 c := &Client{Transport: tr} 1184 res, err := c.Get(ts.URL) 1185 if err != nil { 1186 t.Fatal(err) 1187 } 1188 defer res.Body.Close() 1189 bs, err := ioutil.ReadAll(res.Body) 1190 if err != nil { 1191 t.Fatal(err) 1192 } 1193 if len(bs) != numFoos*len("foo ") { 1194 t.Errorf("unexpected response length") 1195 } 1196 } 1197 1198 // Test that a client receives a server's reply, even if the server doesn't read 1199 // the entire request body. 1200 func TestIssue3595(t *testing.T) { 1201 defer afterTest(t) 1202 const deniedMsg = "sorry, denied." 1203 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1204 Error(w, deniedMsg, StatusUnauthorized) 1205 })) 1206 defer ts.Close() 1207 tr := &Transport{} 1208 c := &Client{Transport: tr} 1209 res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a')) 1210 if err != nil { 1211 t.Errorf("Post: %v", err) 1212 return 1213 } 1214 got, err := ioutil.ReadAll(res.Body) 1215 if err != nil { 1216 t.Fatalf("Body ReadAll: %v", err) 1217 } 1218 if !strings.Contains(string(got), deniedMsg) { 1219 t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg) 1220 } 1221 } 1222 1223 // From https://golang.org/issue/4454 , 1224 // "client fails to handle requests with no body and chunked encoding" 1225 func TestChunkedNoContent(t *testing.T) { 1226 defer afterTest(t) 1227 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1228 w.WriteHeader(StatusNoContent) 1229 })) 1230 defer ts.Close() 1231 1232 for _, closeBody := range []bool{true, false} { 1233 c := &Client{Transport: &Transport{}} 1234 const n = 4 1235 for i := 1; i <= n; i++ { 1236 res, err := c.Get(ts.URL) 1237 if err != nil { 1238 t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err) 1239 } else { 1240 if closeBody { 1241 res.Body.Close() 1242 } 1243 } 1244 } 1245 } 1246 } 1247 1248 func TestTransportConcurrency(t *testing.T) { 1249 defer afterTest(t) 1250 maxProcs, numReqs := 16, 500 1251 if testing.Short() { 1252 maxProcs, numReqs = 4, 50 1253 } 1254 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1255 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1256 fmt.Fprintf(w, "%v", r.FormValue("echo")) 1257 })) 1258 defer ts.Close() 1259 1260 var wg sync.WaitGroup 1261 wg.Add(numReqs) 1262 1263 // Due to the Transport's "socket late binding" (see 1264 // idleConnCh in transport.go), the numReqs HTTP requests 1265 // below can finish with a dial still outstanding. To keep 1266 // the leak checker happy, keep track of pending dials and 1267 // wait for them to finish (and be closed or returned to the 1268 // idle pool) before we close idle connections. 1269 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done) 1270 defer SetPendingDialHooks(nil, nil) 1271 1272 tr := &Transport{} 1273 defer tr.CloseIdleConnections() 1274 1275 c := &Client{Transport: tr} 1276 reqs := make(chan string) 1277 defer close(reqs) 1278 1279 for i := 0; i < maxProcs*2; i++ { 1280 go func() { 1281 for req := range reqs { 1282 res, err := c.Get(ts.URL + "/?echo=" + req) 1283 if err != nil { 1284 t.Errorf("error on req %s: %v", req, err) 1285 wg.Done() 1286 continue 1287 } 1288 all, err := ioutil.ReadAll(res.Body) 1289 if err != nil { 1290 t.Errorf("read error on req %s: %v", req, err) 1291 wg.Done() 1292 continue 1293 } 1294 if string(all) != req { 1295 t.Errorf("body of req %s = %q; want %q", req, all, req) 1296 } 1297 res.Body.Close() 1298 wg.Done() 1299 } 1300 }() 1301 } 1302 for i := 0; i < numReqs; i++ { 1303 reqs <- fmt.Sprintf("request-%d", i) 1304 } 1305 wg.Wait() 1306 } 1307 1308 func TestIssue4191_InfiniteGetTimeout(t *testing.T) { 1309 if runtime.GOOS == "plan9" { 1310 t.Skip("skipping test; see https://golang.org/issue/7237") 1311 } 1312 defer afterTest(t) 1313 const debug = false 1314 mux := NewServeMux() 1315 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1316 io.Copy(w, neverEnding('a')) 1317 }) 1318 ts := httptest.NewServer(mux) 1319 timeout := 100 * time.Millisecond 1320 1321 client := &Client{ 1322 Transport: &Transport{ 1323 Dial: func(n, addr string) (net.Conn, error) { 1324 conn, err := net.Dial(n, addr) 1325 if err != nil { 1326 return nil, err 1327 } 1328 conn.SetDeadline(time.Now().Add(timeout)) 1329 if debug { 1330 conn = NewLoggingConn("client", conn) 1331 } 1332 return conn, nil 1333 }, 1334 DisableKeepAlives: true, 1335 }, 1336 } 1337 1338 getFailed := false 1339 nRuns := 5 1340 if testing.Short() { 1341 nRuns = 1 1342 } 1343 for i := 0; i < nRuns; i++ { 1344 if debug { 1345 println("run", i+1, "of", nRuns) 1346 } 1347 sres, err := client.Get(ts.URL + "/get") 1348 if err != nil { 1349 if !getFailed { 1350 // Make the timeout longer, once. 1351 getFailed = true 1352 t.Logf("increasing timeout") 1353 i-- 1354 timeout *= 10 1355 continue 1356 } 1357 t.Errorf("Error issuing GET: %v", err) 1358 break 1359 } 1360 _, err = io.Copy(ioutil.Discard, sres.Body) 1361 if err == nil { 1362 t.Errorf("Unexpected successful copy") 1363 break 1364 } 1365 } 1366 if debug { 1367 println("tests complete; waiting for handlers to finish") 1368 } 1369 ts.Close() 1370 } 1371 1372 func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) { 1373 if runtime.GOOS == "plan9" { 1374 t.Skip("skipping test; see https://golang.org/issue/7237") 1375 } 1376 defer afterTest(t) 1377 const debug = false 1378 mux := NewServeMux() 1379 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1380 io.Copy(w, neverEnding('a')) 1381 }) 1382 mux.HandleFunc("/put", func(w ResponseWriter, r *Request) { 1383 defer r.Body.Close() 1384 io.Copy(ioutil.Discard, r.Body) 1385 }) 1386 ts := httptest.NewServer(mux) 1387 timeout := 100 * time.Millisecond 1388 1389 client := &Client{ 1390 Transport: &Transport{ 1391 Dial: func(n, addr string) (net.Conn, error) { 1392 conn, err := net.Dial(n, addr) 1393 if err != nil { 1394 return nil, err 1395 } 1396 conn.SetDeadline(time.Now().Add(timeout)) 1397 if debug { 1398 conn = NewLoggingConn("client", conn) 1399 } 1400 return conn, nil 1401 }, 1402 DisableKeepAlives: true, 1403 }, 1404 } 1405 1406 getFailed := false 1407 nRuns := 5 1408 if testing.Short() { 1409 nRuns = 1 1410 } 1411 for i := 0; i < nRuns; i++ { 1412 if debug { 1413 println("run", i+1, "of", nRuns) 1414 } 1415 sres, err := client.Get(ts.URL + "/get") 1416 if err != nil { 1417 if !getFailed { 1418 // Make the timeout longer, once. 1419 getFailed = true 1420 t.Logf("increasing timeout") 1421 i-- 1422 timeout *= 10 1423 continue 1424 } 1425 t.Errorf("Error issuing GET: %v", err) 1426 break 1427 } 1428 req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body) 1429 _, err = client.Do(req) 1430 if err == nil { 1431 sres.Body.Close() 1432 t.Errorf("Unexpected successful PUT") 1433 break 1434 } 1435 sres.Body.Close() 1436 } 1437 if debug { 1438 println("tests complete; waiting for handlers to finish") 1439 } 1440 ts.Close() 1441 } 1442 1443 func TestTransportResponseHeaderTimeout(t *testing.T) { 1444 setParallel(t) 1445 defer afterTest(t) 1446 if testing.Short() { 1447 t.Skip("skipping timeout test in -short mode") 1448 } 1449 inHandler := make(chan bool, 1) 1450 mux := NewServeMux() 1451 mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) { 1452 inHandler <- true 1453 }) 1454 mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) { 1455 inHandler <- true 1456 time.Sleep(2 * time.Second) 1457 }) 1458 ts := httptest.NewServer(mux) 1459 defer ts.Close() 1460 1461 tr := &Transport{ 1462 ResponseHeaderTimeout: 500 * time.Millisecond, 1463 } 1464 defer tr.CloseIdleConnections() 1465 c := &Client{Transport: tr} 1466 1467 tests := []struct { 1468 path string 1469 want int 1470 wantErr string 1471 }{ 1472 {path: "/fast", want: 200}, 1473 {path: "/slow", wantErr: "timeout awaiting response headers"}, 1474 {path: "/fast", want: 200}, 1475 } 1476 for i, tt := range tests { 1477 res, err := c.Get(ts.URL + tt.path) 1478 select { 1479 case <-inHandler: 1480 case <-time.After(5 * time.Second): 1481 t.Errorf("never entered handler for test index %d, %s", i, tt.path) 1482 continue 1483 } 1484 if err != nil { 1485 uerr, ok := err.(*url.Error) 1486 if !ok { 1487 t.Errorf("error is not an url.Error; got: %#v", err) 1488 continue 1489 } 1490 nerr, ok := uerr.Err.(net.Error) 1491 if !ok { 1492 t.Errorf("error does not satisfy net.Error interface; got: %#v", err) 1493 continue 1494 } 1495 if !nerr.Timeout() { 1496 t.Errorf("want timeout error; got: %q", nerr) 1497 continue 1498 } 1499 if strings.Contains(err.Error(), tt.wantErr) { 1500 continue 1501 } 1502 t.Errorf("%d. unexpected error: %v", i, err) 1503 continue 1504 } 1505 if tt.wantErr != "" { 1506 t.Errorf("%d. no error. expected error: %v", i, tt.wantErr) 1507 continue 1508 } 1509 if res.StatusCode != tt.want { 1510 t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want) 1511 } 1512 } 1513 } 1514 1515 func TestTransportCancelRequest(t *testing.T) { 1516 setParallel(t) 1517 defer afterTest(t) 1518 if testing.Short() { 1519 t.Skip("skipping test in -short mode") 1520 } 1521 unblockc := make(chan bool) 1522 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1523 fmt.Fprintf(w, "Hello") 1524 w.(Flusher).Flush() // send headers and some body 1525 <-unblockc 1526 })) 1527 defer ts.Close() 1528 defer close(unblockc) 1529 1530 tr := &Transport{} 1531 defer tr.CloseIdleConnections() 1532 c := &Client{Transport: tr} 1533 1534 req, _ := NewRequest("GET", ts.URL, nil) 1535 res, err := c.Do(req) 1536 if err != nil { 1537 t.Fatal(err) 1538 } 1539 go func() { 1540 time.Sleep(1 * time.Second) 1541 tr.CancelRequest(req) 1542 }() 1543 t0 := time.Now() 1544 body, err := ioutil.ReadAll(res.Body) 1545 d := time.Since(t0) 1546 1547 if err != ExportErrRequestCanceled { 1548 t.Errorf("Body.Read error = %v; want errRequestCanceled", err) 1549 } 1550 if string(body) != "Hello" { 1551 t.Errorf("Body = %q; want Hello", body) 1552 } 1553 if d < 500*time.Millisecond { 1554 t.Errorf("expected ~1 second delay; got %v", d) 1555 } 1556 // Verify no outstanding requests after readLoop/writeLoop 1557 // goroutines shut down. 1558 for tries := 5; tries > 0; tries-- { 1559 n := tr.NumPendingRequestsForTesting() 1560 if n == 0 { 1561 break 1562 } 1563 time.Sleep(100 * time.Millisecond) 1564 if tries == 1 { 1565 t.Errorf("pending requests = %d; want 0", n) 1566 } 1567 } 1568 } 1569 1570 func TestTransportCancelRequestInDial(t *testing.T) { 1571 defer afterTest(t) 1572 if testing.Short() { 1573 t.Skip("skipping test in -short mode") 1574 } 1575 var logbuf bytes.Buffer 1576 eventLog := log.New(&logbuf, "", 0) 1577 1578 unblockDial := make(chan bool) 1579 defer close(unblockDial) 1580 1581 inDial := make(chan bool) 1582 tr := &Transport{ 1583 Dial: func(network, addr string) (net.Conn, error) { 1584 eventLog.Println("dial: blocking") 1585 inDial <- true 1586 <-unblockDial 1587 return nil, errors.New("nope") 1588 }, 1589 } 1590 cl := &Client{Transport: tr} 1591 gotres := make(chan bool) 1592 req, _ := NewRequest("GET", "http://something.no-network.tld/", nil) 1593 go func() { 1594 _, err := cl.Do(req) 1595 eventLog.Printf("Get = %v", err) 1596 gotres <- true 1597 }() 1598 1599 select { 1600 case <-inDial: 1601 case <-time.After(5 * time.Second): 1602 t.Fatal("timeout; never saw blocking dial") 1603 } 1604 1605 eventLog.Printf("canceling") 1606 tr.CancelRequest(req) 1607 tr.CancelRequest(req) // used to panic on second call 1608 1609 select { 1610 case <-gotres: 1611 case <-time.After(5 * time.Second): 1612 panic("hang. events are: " + logbuf.String()) 1613 } 1614 1615 got := logbuf.String() 1616 want := `dial: blocking 1617 canceling 1618 Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection 1619 ` 1620 if got != want { 1621 t.Errorf("Got events:\n%s\nWant:\n%s", got, want) 1622 } 1623 } 1624 1625 func TestCancelRequestWithChannel(t *testing.T) { 1626 setParallel(t) 1627 defer afterTest(t) 1628 if testing.Short() { 1629 t.Skip("skipping test in -short mode") 1630 } 1631 unblockc := make(chan bool) 1632 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1633 fmt.Fprintf(w, "Hello") 1634 w.(Flusher).Flush() // send headers and some body 1635 <-unblockc 1636 })) 1637 defer ts.Close() 1638 defer close(unblockc) 1639 1640 tr := &Transport{} 1641 defer tr.CloseIdleConnections() 1642 c := &Client{Transport: tr} 1643 1644 req, _ := NewRequest("GET", ts.URL, nil) 1645 ch := make(chan struct{}) 1646 req.Cancel = ch 1647 1648 res, err := c.Do(req) 1649 if err != nil { 1650 t.Fatal(err) 1651 } 1652 go func() { 1653 time.Sleep(1 * time.Second) 1654 close(ch) 1655 }() 1656 t0 := time.Now() 1657 body, err := ioutil.ReadAll(res.Body) 1658 d := time.Since(t0) 1659 1660 if err != ExportErrRequestCanceled { 1661 t.Errorf("Body.Read error = %v; want errRequestCanceled", err) 1662 } 1663 if string(body) != "Hello" { 1664 t.Errorf("Body = %q; want Hello", body) 1665 } 1666 if d < 500*time.Millisecond { 1667 t.Errorf("expected ~1 second delay; got %v", d) 1668 } 1669 // Verify no outstanding requests after readLoop/writeLoop 1670 // goroutines shut down. 1671 for tries := 5; tries > 0; tries-- { 1672 n := tr.NumPendingRequestsForTesting() 1673 if n == 0 { 1674 break 1675 } 1676 time.Sleep(100 * time.Millisecond) 1677 if tries == 1 { 1678 t.Errorf("pending requests = %d; want 0", n) 1679 } 1680 } 1681 } 1682 1683 func TestCancelRequestWithChannelBeforeDo_Cancel(t *testing.T) { 1684 testCancelRequestWithChannelBeforeDo(t, false) 1685 } 1686 func TestCancelRequestWithChannelBeforeDo_Context(t *testing.T) { 1687 testCancelRequestWithChannelBeforeDo(t, true) 1688 } 1689 func testCancelRequestWithChannelBeforeDo(t *testing.T, withCtx bool) { 1690 setParallel(t) 1691 defer afterTest(t) 1692 unblockc := make(chan bool) 1693 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1694 <-unblockc 1695 })) 1696 defer ts.Close() 1697 defer close(unblockc) 1698 1699 // Don't interfere with the next test on plan9. 1700 // Cf. https://golang.org/issues/11476 1701 if runtime.GOOS == "plan9" { 1702 defer time.Sleep(500 * time.Millisecond) 1703 } 1704 1705 tr := &Transport{} 1706 defer tr.CloseIdleConnections() 1707 c := &Client{Transport: tr} 1708 1709 req, _ := NewRequest("GET", ts.URL, nil) 1710 if withCtx { 1711 ctx, cancel := context.WithCancel(context.Background()) 1712 cancel() 1713 req = req.WithContext(ctx) 1714 } else { 1715 ch := make(chan struct{}) 1716 req.Cancel = ch 1717 close(ch) 1718 } 1719 1720 _, err := c.Do(req) 1721 if err == nil || !strings.Contains(err.Error(), "canceled") { 1722 t.Errorf("Do error = %v; want cancelation", err) 1723 } 1724 } 1725 1726 // Issue 11020. The returned error message should be errRequestCanceled 1727 func TestTransportCancelBeforeResponseHeaders(t *testing.T) { 1728 defer afterTest(t) 1729 1730 serverConnCh := make(chan net.Conn, 1) 1731 tr := &Transport{ 1732 Dial: func(network, addr string) (net.Conn, error) { 1733 cc, sc := net.Pipe() 1734 serverConnCh <- sc 1735 return cc, nil 1736 }, 1737 } 1738 defer tr.CloseIdleConnections() 1739 errc := make(chan error, 1) 1740 req, _ := NewRequest("GET", "http://example.com/", nil) 1741 go func() { 1742 _, err := tr.RoundTrip(req) 1743 errc <- err 1744 }() 1745 1746 sc := <-serverConnCh 1747 verb := make([]byte, 3) 1748 if _, err := io.ReadFull(sc, verb); err != nil { 1749 t.Errorf("Error reading HTTP verb from server: %v", err) 1750 } 1751 if string(verb) != "GET" { 1752 t.Errorf("server received %q; want GET", verb) 1753 } 1754 defer sc.Close() 1755 1756 tr.CancelRequest(req) 1757 1758 err := <-errc 1759 if err == nil { 1760 t.Fatalf("unexpected success from RoundTrip") 1761 } 1762 if err != ExportErrRequestCanceled { 1763 t.Errorf("RoundTrip error = %v; want ExportErrRequestCanceled", err) 1764 } 1765 } 1766 1767 // golang.org/issue/3672 -- Client can't close HTTP stream 1768 // Calling Close on a Response.Body used to just read until EOF. 1769 // Now it actually closes the TCP connection. 1770 func TestTransportCloseResponseBody(t *testing.T) { 1771 defer afterTest(t) 1772 writeErr := make(chan error, 1) 1773 msg := []byte("young\n") 1774 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1775 for { 1776 _, err := w.Write(msg) 1777 if err != nil { 1778 writeErr <- err 1779 return 1780 } 1781 w.(Flusher).Flush() 1782 } 1783 })) 1784 defer ts.Close() 1785 1786 tr := &Transport{} 1787 defer tr.CloseIdleConnections() 1788 c := &Client{Transport: tr} 1789 1790 req, _ := NewRequest("GET", ts.URL, nil) 1791 defer tr.CancelRequest(req) 1792 1793 res, err := c.Do(req) 1794 if err != nil { 1795 t.Fatal(err) 1796 } 1797 1798 const repeats = 3 1799 buf := make([]byte, len(msg)*repeats) 1800 want := bytes.Repeat(msg, repeats) 1801 1802 _, err = io.ReadFull(res.Body, buf) 1803 if err != nil { 1804 t.Fatal(err) 1805 } 1806 if !bytes.Equal(buf, want) { 1807 t.Fatalf("read %q; want %q", buf, want) 1808 } 1809 didClose := make(chan error, 1) 1810 go func() { 1811 didClose <- res.Body.Close() 1812 }() 1813 select { 1814 case err := <-didClose: 1815 if err != nil { 1816 t.Errorf("Close = %v", err) 1817 } 1818 case <-time.After(10 * time.Second): 1819 t.Fatal("too long waiting for close") 1820 } 1821 select { 1822 case err := <-writeErr: 1823 if err == nil { 1824 t.Errorf("expected non-nil write error") 1825 } 1826 case <-time.After(10 * time.Second): 1827 t.Fatal("too long waiting for write error") 1828 } 1829 } 1830 1831 type fooProto struct{} 1832 1833 func (fooProto) RoundTrip(req *Request) (*Response, error) { 1834 res := &Response{ 1835 Status: "200 OK", 1836 StatusCode: 200, 1837 Header: make(Header), 1838 Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())), 1839 } 1840 return res, nil 1841 } 1842 1843 func TestTransportAltProto(t *testing.T) { 1844 defer afterTest(t) 1845 tr := &Transport{} 1846 c := &Client{Transport: tr} 1847 tr.RegisterProtocol("foo", fooProto{}) 1848 res, err := c.Get("foo://bar.com/path") 1849 if err != nil { 1850 t.Fatal(err) 1851 } 1852 bodyb, err := ioutil.ReadAll(res.Body) 1853 if err != nil { 1854 t.Fatal(err) 1855 } 1856 body := string(bodyb) 1857 if e := "You wanted foo://bar.com/path"; body != e { 1858 t.Errorf("got response %q, want %q", body, e) 1859 } 1860 } 1861 1862 func TestTransportNoHost(t *testing.T) { 1863 defer afterTest(t) 1864 tr := &Transport{} 1865 _, err := tr.RoundTrip(&Request{ 1866 Header: make(Header), 1867 URL: &url.URL{ 1868 Scheme: "http", 1869 }, 1870 }) 1871 want := "http: no Host in request URL" 1872 if got := fmt.Sprint(err); got != want { 1873 t.Errorf("error = %v; want %q", err, want) 1874 } 1875 } 1876 1877 // Issue 13311 1878 func TestTransportEmptyMethod(t *testing.T) { 1879 req, _ := NewRequest("GET", "http://foo.com/", nil) 1880 req.Method = "" // docs say "For client requests an empty string means GET" 1881 got, err := httputil.DumpRequestOut(req, false) // DumpRequestOut uses Transport 1882 if err != nil { 1883 t.Fatal(err) 1884 } 1885 if !strings.Contains(string(got), "GET ") { 1886 t.Fatalf("expected substring 'GET '; got: %s", got) 1887 } 1888 } 1889 1890 func TestTransportSocketLateBinding(t *testing.T) { 1891 defer afterTest(t) 1892 1893 mux := NewServeMux() 1894 fooGate := make(chan bool, 1) 1895 mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) { 1896 w.Header().Set("foo-ipport", r.RemoteAddr) 1897 w.(Flusher).Flush() 1898 <-fooGate 1899 }) 1900 mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) { 1901 w.Header().Set("bar-ipport", r.RemoteAddr) 1902 }) 1903 ts := httptest.NewServer(mux) 1904 defer ts.Close() 1905 1906 dialGate := make(chan bool, 1) 1907 tr := &Transport{ 1908 Dial: func(n, addr string) (net.Conn, error) { 1909 if <-dialGate { 1910 return net.Dial(n, addr) 1911 } 1912 return nil, errors.New("manually closed") 1913 }, 1914 DisableKeepAlives: false, 1915 } 1916 defer tr.CloseIdleConnections() 1917 c := &Client{ 1918 Transport: tr, 1919 } 1920 1921 dialGate <- true // only allow one dial 1922 fooRes, err := c.Get(ts.URL + "/foo") 1923 if err != nil { 1924 t.Fatal(err) 1925 } 1926 fooAddr := fooRes.Header.Get("foo-ipport") 1927 if fooAddr == "" { 1928 t.Fatal("No addr on /foo request") 1929 } 1930 time.AfterFunc(200*time.Millisecond, func() { 1931 // let the foo response finish so we can use its 1932 // connection for /bar 1933 fooGate <- true 1934 io.Copy(ioutil.Discard, fooRes.Body) 1935 fooRes.Body.Close() 1936 }) 1937 1938 barRes, err := c.Get(ts.URL + "/bar") 1939 if err != nil { 1940 t.Fatal(err) 1941 } 1942 barAddr := barRes.Header.Get("bar-ipport") 1943 if barAddr != fooAddr { 1944 t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr) 1945 } 1946 barRes.Body.Close() 1947 dialGate <- false 1948 } 1949 1950 // Issue 2184 1951 func TestTransportReading100Continue(t *testing.T) { 1952 defer afterTest(t) 1953 1954 const numReqs = 5 1955 reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) } 1956 reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) } 1957 1958 send100Response := func(w *io.PipeWriter, r *io.PipeReader) { 1959 defer w.Close() 1960 defer r.Close() 1961 br := bufio.NewReader(r) 1962 n := 0 1963 for { 1964 n++ 1965 req, err := ReadRequest(br) 1966 if err == io.EOF { 1967 return 1968 } 1969 if err != nil { 1970 t.Error(err) 1971 return 1972 } 1973 slurp, err := ioutil.ReadAll(req.Body) 1974 if err != nil { 1975 t.Errorf("Server request body slurp: %v", err) 1976 return 1977 } 1978 id := req.Header.Get("Request-Id") 1979 resCode := req.Header.Get("X-Want-Response-Code") 1980 if resCode == "" { 1981 resCode = "100 Continue" 1982 if string(slurp) != reqBody(n) { 1983 t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n)) 1984 } 1985 } 1986 body := fmt.Sprintf("Response number %d", n) 1987 v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s 1988 Date: Thu, 28 Feb 2013 17:55:41 GMT 1989 1990 HTTP/1.1 200 OK 1991 Content-Type: text/html 1992 Echo-Request-Id: %s 1993 Content-Length: %d 1994 1995 %s`, resCode, id, len(body), body), "\n", "\r\n", -1)) 1996 w.Write(v) 1997 if id == reqID(numReqs) { 1998 return 1999 } 2000 } 2001 2002 } 2003 2004 tr := &Transport{ 2005 Dial: func(n, addr string) (net.Conn, error) { 2006 sr, sw := io.Pipe() // server read/write 2007 cr, cw := io.Pipe() // client read/write 2008 conn := &rwTestConn{ 2009 Reader: cr, 2010 Writer: sw, 2011 closeFunc: func() error { 2012 sw.Close() 2013 cw.Close() 2014 return nil 2015 }, 2016 } 2017 go send100Response(cw, sr) 2018 return conn, nil 2019 }, 2020 DisableKeepAlives: false, 2021 } 2022 defer tr.CloseIdleConnections() 2023 c := &Client{Transport: tr} 2024 2025 testResponse := func(req *Request, name string, wantCode int) { 2026 res, err := c.Do(req) 2027 if err != nil { 2028 t.Fatalf("%s: Do: %v", name, err) 2029 } 2030 if res.StatusCode != wantCode { 2031 t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode) 2032 } 2033 if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack { 2034 t.Errorf("%s: response id %q != request id %q", name, idBack, id) 2035 } 2036 _, err = ioutil.ReadAll(res.Body) 2037 if err != nil { 2038 t.Fatalf("%s: Slurp error: %v", name, err) 2039 } 2040 } 2041 2042 // Few 100 responses, making sure we're not off-by-one. 2043 for i := 1; i <= numReqs; i++ { 2044 req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i))) 2045 req.Header.Set("Request-Id", reqID(i)) 2046 testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200) 2047 } 2048 2049 // And some other informational 1xx but non-100 responses, to test 2050 // we return them but don't re-use the connection. 2051 for i := 1; i <= numReqs; i++ { 2052 req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i))) 2053 req.Header.Set("X-Want-Response-Code", "123 Sesame Street") 2054 testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123) 2055 } 2056 } 2057 2058 type proxyFromEnvTest struct { 2059 req string // URL to fetch; blank means "http://example.com" 2060 2061 env string // HTTP_PROXY 2062 httpsenv string // HTTPS_PROXY 2063 noenv string // NO_RPXY 2064 2065 want string 2066 wanterr error 2067 } 2068 2069 func (t proxyFromEnvTest) String() string { 2070 var buf bytes.Buffer 2071 space := func() { 2072 if buf.Len() > 0 { 2073 buf.WriteByte(' ') 2074 } 2075 } 2076 if t.env != "" { 2077 fmt.Fprintf(&buf, "http_proxy=%q", t.env) 2078 } 2079 if t.httpsenv != "" { 2080 space() 2081 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv) 2082 } 2083 if t.noenv != "" { 2084 space() 2085 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv) 2086 } 2087 req := "http://example.com" 2088 if t.req != "" { 2089 req = t.req 2090 } 2091 space() 2092 fmt.Fprintf(&buf, "req=%q", req) 2093 return strings.TrimSpace(buf.String()) 2094 } 2095 2096 var proxyFromEnvTests = []proxyFromEnvTest{ 2097 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2098 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"}, 2099 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"}, 2100 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"}, 2101 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2102 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"}, 2103 2104 // Don't use secure for http 2105 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"}, 2106 // Use secure for https. 2107 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"}, 2108 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"}, 2109 2110 {want: "<nil>"}, 2111 2112 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2113 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2114 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2115 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"}, 2116 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2117 } 2118 2119 func TestProxyFromEnvironment(t *testing.T) { 2120 ResetProxyEnv() 2121 for _, tt := range proxyFromEnvTests { 2122 os.Setenv("HTTP_PROXY", tt.env) 2123 os.Setenv("HTTPS_PROXY", tt.httpsenv) 2124 os.Setenv("NO_PROXY", tt.noenv) 2125 ResetCachedEnvironment() 2126 reqURL := tt.req 2127 if reqURL == "" { 2128 reqURL = "http://example.com" 2129 } 2130 req, _ := NewRequest("GET", reqURL, nil) 2131 url, err := ProxyFromEnvironment(req) 2132 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 2133 t.Errorf("%v: got error = %q, want %q", tt, g, e) 2134 continue 2135 } 2136 if got := fmt.Sprintf("%s", url); got != tt.want { 2137 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 2138 } 2139 } 2140 } 2141 2142 func TestIdleConnChannelLeak(t *testing.T) { 2143 var mu sync.Mutex 2144 var n int 2145 2146 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2147 mu.Lock() 2148 n++ 2149 mu.Unlock() 2150 })) 2151 defer ts.Close() 2152 2153 const nReqs = 5 2154 didRead := make(chan bool, nReqs) 2155 SetReadLoopBeforeNextReadHook(func() { didRead <- true }) 2156 defer SetReadLoopBeforeNextReadHook(nil) 2157 2158 tr := &Transport{ 2159 Dial: func(netw, addr string) (net.Conn, error) { 2160 return net.Dial(netw, ts.Listener.Addr().String()) 2161 }, 2162 } 2163 defer tr.CloseIdleConnections() 2164 2165 c := &Client{Transport: tr} 2166 2167 // First, without keep-alives. 2168 for _, disableKeep := range []bool{true, false} { 2169 tr.DisableKeepAlives = disableKeep 2170 for i := 0; i < nReqs; i++ { 2171 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i)) 2172 if err != nil { 2173 t.Fatal(err) 2174 } 2175 // Note: no res.Body.Close is needed here, since the 2176 // response Content-Length is zero. Perhaps the test 2177 // should be more explicit and use a HEAD, but tests 2178 // elsewhere guarantee that zero byte responses generate 2179 // a "Content-Length: 0" instead of chunking. 2180 } 2181 2182 // At this point, each of the 5 Transport.readLoop goroutines 2183 // are scheduling noting that there are no response bodies (see 2184 // earlier comment), and are then calling putIdleConn, which 2185 // decrements this count. Usually that happens quickly, which is 2186 // why this test has seemed to work for ages. But it's still 2187 // racey: we have wait for them to finish first. See Issue 10427 2188 for i := 0; i < nReqs; i++ { 2189 <-didRead 2190 } 2191 2192 if got := tr.IdleConnChMapSizeForTesting(); got != 0 { 2193 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got) 2194 } 2195 } 2196 } 2197 2198 // Verify the status quo: that the Client.Post function coerces its 2199 // body into a ReadCloser if it's a Closer, and that the Transport 2200 // then closes it. 2201 func TestTransportClosesRequestBody(t *testing.T) { 2202 defer afterTest(t) 2203 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2204 io.Copy(ioutil.Discard, r.Body) 2205 })) 2206 defer ts.Close() 2207 2208 tr := &Transport{} 2209 defer tr.CloseIdleConnections() 2210 cl := &Client{Transport: tr} 2211 2212 closes := 0 2213 2214 res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")}) 2215 if err != nil { 2216 t.Fatal(err) 2217 } 2218 res.Body.Close() 2219 if closes != 1 { 2220 t.Errorf("closes = %d; want 1", closes) 2221 } 2222 } 2223 2224 func TestTransportTLSHandshakeTimeout(t *testing.T) { 2225 defer afterTest(t) 2226 if testing.Short() { 2227 t.Skip("skipping in short mode") 2228 } 2229 ln := newLocalListener(t) 2230 defer ln.Close() 2231 testdonec := make(chan struct{}) 2232 defer close(testdonec) 2233 2234 go func() { 2235 c, err := ln.Accept() 2236 if err != nil { 2237 t.Error(err) 2238 return 2239 } 2240 <-testdonec 2241 c.Close() 2242 }() 2243 2244 getdonec := make(chan struct{}) 2245 go func() { 2246 defer close(getdonec) 2247 tr := &Transport{ 2248 Dial: func(_, _ string) (net.Conn, error) { 2249 return net.Dial("tcp", ln.Addr().String()) 2250 }, 2251 TLSHandshakeTimeout: 250 * time.Millisecond, 2252 } 2253 cl := &Client{Transport: tr} 2254 _, err := cl.Get("https://dummy.tld/") 2255 if err == nil { 2256 t.Error("expected error") 2257 return 2258 } 2259 ue, ok := err.(*url.Error) 2260 if !ok { 2261 t.Errorf("expected url.Error; got %#v", err) 2262 return 2263 } 2264 ne, ok := ue.Err.(net.Error) 2265 if !ok { 2266 t.Errorf("expected net.Error; got %#v", err) 2267 return 2268 } 2269 if !ne.Timeout() { 2270 t.Errorf("expected timeout error; got %v", err) 2271 } 2272 if !strings.Contains(err.Error(), "handshake timeout") { 2273 t.Errorf("expected 'handshake timeout' in error; got %v", err) 2274 } 2275 }() 2276 select { 2277 case <-getdonec: 2278 case <-time.After(5 * time.Second): 2279 t.Error("test timeout; TLS handshake hung?") 2280 } 2281 } 2282 2283 // Trying to repro golang.org/issue/3514 2284 func TestTLSServerClosesConnection(t *testing.T) { 2285 defer afterTest(t) 2286 testenv.SkipFlaky(t, 7634) 2287 2288 closedc := make(chan bool, 1) 2289 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2290 if strings.Contains(r.URL.Path, "/keep-alive-then-die") { 2291 conn, _, _ := w.(Hijacker).Hijack() 2292 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) 2293 conn.Close() 2294 closedc <- true 2295 return 2296 } 2297 fmt.Fprintf(w, "hello") 2298 })) 2299 defer ts.Close() 2300 tr := &Transport{ 2301 TLSClientConfig: &tls.Config{ 2302 InsecureSkipVerify: true, 2303 }, 2304 } 2305 defer tr.CloseIdleConnections() 2306 client := &Client{Transport: tr} 2307 2308 var nSuccess = 0 2309 var errs []error 2310 const trials = 20 2311 for i := 0; i < trials; i++ { 2312 tr.CloseIdleConnections() 2313 res, err := client.Get(ts.URL + "/keep-alive-then-die") 2314 if err != nil { 2315 t.Fatal(err) 2316 } 2317 <-closedc 2318 slurp, err := ioutil.ReadAll(res.Body) 2319 if err != nil { 2320 t.Fatal(err) 2321 } 2322 if string(slurp) != "foo" { 2323 t.Errorf("Got %q, want foo", slurp) 2324 } 2325 2326 // Now try again and see if we successfully 2327 // pick a new connection. 2328 res, err = client.Get(ts.URL + "/") 2329 if err != nil { 2330 errs = append(errs, err) 2331 continue 2332 } 2333 slurp, err = ioutil.ReadAll(res.Body) 2334 if err != nil { 2335 errs = append(errs, err) 2336 continue 2337 } 2338 nSuccess++ 2339 } 2340 if nSuccess > 0 { 2341 t.Logf("successes = %d of %d", nSuccess, trials) 2342 } else { 2343 t.Errorf("All runs failed:") 2344 } 2345 for _, err := range errs { 2346 t.Logf(" err: %v", err) 2347 } 2348 } 2349 2350 // byteFromChanReader is an io.Reader that reads a single byte at a 2351 // time from the channel. When the channel is closed, the reader 2352 // returns io.EOF. 2353 type byteFromChanReader chan byte 2354 2355 func (c byteFromChanReader) Read(p []byte) (n int, err error) { 2356 if len(p) == 0 { 2357 return 2358 } 2359 b, ok := <-c 2360 if !ok { 2361 return 0, io.EOF 2362 } 2363 p[0] = b 2364 return 1, nil 2365 } 2366 2367 // Verifies that the Transport doesn't reuse a connection in the case 2368 // where the server replies before the request has been fully 2369 // written. We still honor that reply (see TestIssue3595), but don't 2370 // send future requests on the connection because it's then in a 2371 // questionable state. 2372 // golang.org/issue/7569 2373 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) { 2374 defer afterTest(t) 2375 var sconn struct { 2376 sync.Mutex 2377 c net.Conn 2378 } 2379 var getOkay bool 2380 closeConn := func() { 2381 sconn.Lock() 2382 defer sconn.Unlock() 2383 if sconn.c != nil { 2384 sconn.c.Close() 2385 sconn.c = nil 2386 if !getOkay { 2387 t.Logf("Closed server connection") 2388 } 2389 } 2390 } 2391 defer closeConn() 2392 2393 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2394 if r.Method == "GET" { 2395 io.WriteString(w, "bar") 2396 return 2397 } 2398 conn, _, _ := w.(Hijacker).Hijack() 2399 sconn.Lock() 2400 sconn.c = conn 2401 sconn.Unlock() 2402 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive 2403 go io.Copy(ioutil.Discard, conn) 2404 })) 2405 defer ts.Close() 2406 tr := &Transport{} 2407 defer tr.CloseIdleConnections() 2408 client := &Client{Transport: tr} 2409 2410 const bodySize = 256 << 10 2411 finalBit := make(byteFromChanReader, 1) 2412 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit)) 2413 req.ContentLength = bodySize 2414 res, err := client.Do(req) 2415 if err := wantBody(res, err, "foo"); err != nil { 2416 t.Errorf("POST response: %v", err) 2417 } 2418 donec := make(chan bool) 2419 go func() { 2420 defer close(donec) 2421 res, err = client.Get(ts.URL) 2422 if err := wantBody(res, err, "bar"); err != nil { 2423 t.Errorf("GET response: %v", err) 2424 return 2425 } 2426 getOkay = true // suppress test noise 2427 }() 2428 time.AfterFunc(5*time.Second, closeConn) 2429 select { 2430 case <-donec: 2431 finalBit <- 'x' // unblock the writeloop of the first Post 2432 close(finalBit) 2433 case <-time.After(7 * time.Second): 2434 t.Fatal("timeout waiting for GET request to finish") 2435 } 2436 } 2437 2438 // Tests that we don't leak Transport persistConn.readLoop goroutines 2439 // when a server hangs up immediately after saying it would keep-alive. 2440 func TestTransportIssue10457(t *testing.T) { 2441 defer afterTest(t) // used to fail in goroutine leak check 2442 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2443 // Send a response with no body, keep-alive 2444 // (implicit), and then lie and immediately close the 2445 // connection. This forces the Transport's readLoop to 2446 // immediately Peek an io.EOF and get to the point 2447 // that used to hang. 2448 conn, _, _ := w.(Hijacker).Hijack() 2449 conn.Write([]byte("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 0\r\n\r\n")) // keep-alive 2450 conn.Close() 2451 })) 2452 defer ts.Close() 2453 tr := &Transport{} 2454 defer tr.CloseIdleConnections() 2455 cl := &Client{Transport: tr} 2456 res, err := cl.Get(ts.URL) 2457 if err != nil { 2458 t.Fatalf("Get: %v", err) 2459 } 2460 defer res.Body.Close() 2461 2462 // Just a sanity check that we at least get the response. The real 2463 // test here is that the "defer afterTest" above doesn't find any 2464 // leaked goroutines. 2465 if got, want := res.Header.Get("Foo"), "Bar"; got != want { 2466 t.Errorf("Foo header = %q; want %q", got, want) 2467 } 2468 } 2469 2470 type errorReader struct { 2471 err error 2472 } 2473 2474 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err } 2475 2476 type plan9SleepReader struct{} 2477 2478 func (plan9SleepReader) Read(p []byte) (int, error) { 2479 if runtime.GOOS == "plan9" { 2480 // After the fix to unblock TCP Reads in 2481 // https://golang.org/cl/15941, this sleep is required 2482 // on plan9 to make sure TCP Writes before an 2483 // immediate TCP close go out on the wire. On Plan 9, 2484 // it seems that a hangup of a TCP connection with 2485 // queued data doesn't send the queued data first. 2486 // https://golang.org/issue/9554 2487 time.Sleep(50 * time.Millisecond) 2488 } 2489 return 0, io.EOF 2490 } 2491 2492 type closerFunc func() error 2493 2494 func (f closerFunc) Close() error { return f() } 2495 2496 // Issue 4677. If we try to reuse a connection that the server is in the 2497 // process of closing, we may end up successfully writing out our request (or a 2498 // portion of our request) only to find a connection error when we try to read 2499 // from (or finish writing to) the socket. 2500 // 2501 // NOTE: we resend a request only if the request is idempotent, we reused a 2502 // keep-alive connection, and we haven't yet received any header data. This 2503 // automatically prevents an infinite resend loop because we'll run out of the 2504 // cached keep-alive connections eventually. 2505 func TestRetryIdempotentRequestsOnError(t *testing.T) { 2506 defer afterTest(t) 2507 2508 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2509 })) 2510 defer ts.Close() 2511 2512 tr := &Transport{} 2513 c := &Client{Transport: tr} 2514 2515 const N = 2 2516 retryc := make(chan struct{}, N) 2517 SetRoundTripRetried(func() { 2518 retryc <- struct{}{} 2519 }) 2520 defer SetRoundTripRetried(nil) 2521 2522 for n := 0; n < 100; n++ { 2523 // open 2 conns 2524 errc := make(chan error, N) 2525 for i := 0; i < N; i++ { 2526 // start goroutines, send on errc 2527 go func() { 2528 res, err := c.Get(ts.URL) 2529 if err == nil { 2530 res.Body.Close() 2531 } 2532 errc <- err 2533 }() 2534 } 2535 for i := 0; i < N; i++ { 2536 if err := <-errc; err != nil { 2537 t.Fatal(err) 2538 } 2539 } 2540 2541 ts.CloseClientConnections() 2542 for i := 0; i < N; i++ { 2543 go func() { 2544 res, err := c.Get(ts.URL) 2545 if err == nil { 2546 res.Body.Close() 2547 } 2548 errc <- err 2549 }() 2550 } 2551 2552 for i := 0; i < N; i++ { 2553 if err := <-errc; err != nil { 2554 t.Fatal(err) 2555 } 2556 } 2557 for i := 0; i < N; i++ { 2558 select { 2559 case <-retryc: 2560 // we triggered a retry, test was successful 2561 t.Logf("finished after %d runs\n", n) 2562 return 2563 default: 2564 } 2565 } 2566 } 2567 t.Fatal("did not trigger any retries") 2568 } 2569 2570 // Issue 6981 2571 func TestTransportClosesBodyOnError(t *testing.T) { 2572 setParallel(t) 2573 defer afterTest(t) 2574 readBody := make(chan error, 1) 2575 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2576 _, err := ioutil.ReadAll(r.Body) 2577 readBody <- err 2578 })) 2579 defer ts.Close() 2580 fakeErr := errors.New("fake error") 2581 didClose := make(chan bool, 1) 2582 req, _ := NewRequest("POST", ts.URL, struct { 2583 io.Reader 2584 io.Closer 2585 }{ 2586 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), plan9SleepReader{}, errorReader{fakeErr}), 2587 closerFunc(func() error { 2588 select { 2589 case didClose <- true: 2590 default: 2591 } 2592 return nil 2593 }), 2594 }) 2595 res, err := DefaultClient.Do(req) 2596 if res != nil { 2597 defer res.Body.Close() 2598 } 2599 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 2600 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 2601 } 2602 select { 2603 case err := <-readBody: 2604 if err == nil { 2605 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 2606 } 2607 case <-time.After(5 * time.Second): 2608 t.Error("timeout waiting for server handler to complete") 2609 } 2610 select { 2611 case <-didClose: 2612 default: 2613 t.Errorf("didn't see Body.Close") 2614 } 2615 } 2616 2617 func TestTransportDialTLS(t *testing.T) { 2618 var mu sync.Mutex // guards following 2619 var gotReq, didDial bool 2620 2621 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2622 mu.Lock() 2623 gotReq = true 2624 mu.Unlock() 2625 })) 2626 defer ts.Close() 2627 tr := &Transport{ 2628 DialTLS: func(netw, addr string) (net.Conn, error) { 2629 mu.Lock() 2630 didDial = true 2631 mu.Unlock() 2632 c, err := tls.Dial(netw, addr, &tls.Config{ 2633 InsecureSkipVerify: true, 2634 }) 2635 if err != nil { 2636 return nil, err 2637 } 2638 return c, c.Handshake() 2639 }, 2640 } 2641 defer tr.CloseIdleConnections() 2642 client := &Client{Transport: tr} 2643 res, err := client.Get(ts.URL) 2644 if err != nil { 2645 t.Fatal(err) 2646 } 2647 res.Body.Close() 2648 mu.Lock() 2649 if !gotReq { 2650 t.Error("didn't get request") 2651 } 2652 if !didDial { 2653 t.Error("didn't use dial hook") 2654 } 2655 } 2656 2657 // Test for issue 8755 2658 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 2659 func TestRoundTripReturnsProxyError(t *testing.T) { 2660 badProxy := func(*Request) (*url.URL, error) { 2661 return nil, errors.New("errorMessage") 2662 } 2663 2664 tr := &Transport{Proxy: badProxy} 2665 2666 req, _ := NewRequest("GET", "http://example.com", nil) 2667 2668 _, err := tr.RoundTrip(req) 2669 2670 if err == nil { 2671 t.Error("Expected proxy error to be returned by RoundTrip") 2672 } 2673 } 2674 2675 // tests that putting an idle conn after a call to CloseIdleConns does return it 2676 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 2677 tr := &Transport{} 2678 wantIdle := func(when string, n int) bool { 2679 got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn 2680 if got == n { 2681 return true 2682 } 2683 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 2684 return false 2685 } 2686 wantIdle("start", 0) 2687 if !tr.PutIdleTestConn() { 2688 t.Fatal("put failed") 2689 } 2690 if !tr.PutIdleTestConn() { 2691 t.Fatal("second put failed") 2692 } 2693 wantIdle("after put", 2) 2694 tr.CloseIdleConnections() 2695 if !tr.IsIdleForTesting() { 2696 t.Error("should be idle after CloseIdleConnections") 2697 } 2698 wantIdle("after close idle", 0) 2699 if tr.PutIdleTestConn() { 2700 t.Fatal("put didn't fail") 2701 } 2702 wantIdle("after second put", 0) 2703 2704 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode 2705 if tr.IsIdleForTesting() { 2706 t.Error("shouldn't be idle after RequestIdleConnChForTesting") 2707 } 2708 if !tr.PutIdleTestConn() { 2709 t.Fatal("after re-activation") 2710 } 2711 wantIdle("after final put", 1) 2712 } 2713 2714 // This tests that an client requesting a content range won't also 2715 // implicitly ask for gzip support. If they want that, they need to do it 2716 // on their own. 2717 // golang.org/issue/8923 2718 func TestTransportRangeAndGzip(t *testing.T) { 2719 defer afterTest(t) 2720 reqc := make(chan *Request, 1) 2721 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2722 reqc <- r 2723 })) 2724 defer ts.Close() 2725 2726 req, _ := NewRequest("GET", ts.URL, nil) 2727 req.Header.Set("Range", "bytes=7-11") 2728 res, err := DefaultClient.Do(req) 2729 if err != nil { 2730 t.Fatal(err) 2731 } 2732 2733 select { 2734 case r := <-reqc: 2735 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 2736 t.Error("Transport advertised gzip support in the Accept header") 2737 } 2738 if r.Header.Get("Range") == "" { 2739 t.Error("no Range in request") 2740 } 2741 case <-time.After(10 * time.Second): 2742 t.Fatal("timeout") 2743 } 2744 res.Body.Close() 2745 } 2746 2747 // Test for issue 10474 2748 func TestTransportResponseCancelRace(t *testing.T) { 2749 defer afterTest(t) 2750 2751 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2752 // important that this response has a body. 2753 var b [1024]byte 2754 w.Write(b[:]) 2755 })) 2756 defer ts.Close() 2757 2758 tr := &Transport{} 2759 defer tr.CloseIdleConnections() 2760 2761 req, err := NewRequest("GET", ts.URL, nil) 2762 if err != nil { 2763 t.Fatal(err) 2764 } 2765 res, err := tr.RoundTrip(req) 2766 if err != nil { 2767 t.Fatal(err) 2768 } 2769 // If we do an early close, Transport just throws the connection away and 2770 // doesn't reuse it. In order to trigger the bug, it has to reuse the connection 2771 // so read the body 2772 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { 2773 t.Fatal(err) 2774 } 2775 2776 req2, err := NewRequest("GET", ts.URL, nil) 2777 if err != nil { 2778 t.Fatal(err) 2779 } 2780 tr.CancelRequest(req) 2781 res, err = tr.RoundTrip(req2) 2782 if err != nil { 2783 t.Fatal(err) 2784 } 2785 res.Body.Close() 2786 } 2787 2788 func TestTransportDialCancelRace(t *testing.T) { 2789 defer afterTest(t) 2790 2791 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 2792 defer ts.Close() 2793 2794 tr := &Transport{} 2795 defer tr.CloseIdleConnections() 2796 2797 req, err := NewRequest("GET", ts.URL, nil) 2798 if err != nil { 2799 t.Fatal(err) 2800 } 2801 SetEnterRoundTripHook(func() { 2802 tr.CancelRequest(req) 2803 }) 2804 defer SetEnterRoundTripHook(nil) 2805 res, err := tr.RoundTrip(req) 2806 if err != ExportErrRequestCanceled { 2807 t.Errorf("expected canceled request error; got %v", err) 2808 if err == nil { 2809 res.Body.Close() 2810 } 2811 } 2812 } 2813 2814 // logWritesConn is a net.Conn that logs each Write call to writes 2815 // and then proxies to w. 2816 // It proxies Read calls to a reader it receives from rch. 2817 type logWritesConn struct { 2818 net.Conn // nil. crash on use. 2819 2820 w io.Writer 2821 2822 rch <-chan io.Reader 2823 r io.Reader // nil until received by rch 2824 2825 mu sync.Mutex 2826 writes []string 2827 } 2828 2829 func (c *logWritesConn) Write(p []byte) (n int, err error) { 2830 c.mu.Lock() 2831 defer c.mu.Unlock() 2832 c.writes = append(c.writes, string(p)) 2833 return c.w.Write(p) 2834 } 2835 2836 func (c *logWritesConn) Read(p []byte) (n int, err error) { 2837 if c.r == nil { 2838 c.r = <-c.rch 2839 } 2840 return c.r.Read(p) 2841 } 2842 2843 func (c *logWritesConn) Close() error { return nil } 2844 2845 // Issue 6574 2846 func TestTransportFlushesBodyChunks(t *testing.T) { 2847 defer afterTest(t) 2848 resBody := make(chan io.Reader, 1) 2849 connr, connw := io.Pipe() // connection pipe pair 2850 lw := &logWritesConn{ 2851 rch: resBody, 2852 w: connw, 2853 } 2854 tr := &Transport{ 2855 Dial: func(network, addr string) (net.Conn, error) { 2856 return lw, nil 2857 }, 2858 } 2859 bodyr, bodyw := io.Pipe() // body pipe pair 2860 go func() { 2861 defer bodyw.Close() 2862 for i := 0; i < 3; i++ { 2863 fmt.Fprintf(bodyw, "num%d\n", i) 2864 } 2865 }() 2866 resc := make(chan *Response) 2867 go func() { 2868 req, _ := NewRequest("POST", "http://localhost:8080", bodyr) 2869 req.Header.Set("User-Agent", "x") // known value for test 2870 res, err := tr.RoundTrip(req) 2871 if err != nil { 2872 t.Errorf("RoundTrip: %v", err) 2873 close(resc) 2874 return 2875 } 2876 resc <- res 2877 2878 }() 2879 // Fully consume the request before checking the Write log vs. want. 2880 req, err := ReadRequest(bufio.NewReader(connr)) 2881 if err != nil { 2882 t.Fatal(err) 2883 } 2884 io.Copy(ioutil.Discard, req.Body) 2885 2886 // Unblock the transport's roundTrip goroutine. 2887 resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n") 2888 res, ok := <-resc 2889 if !ok { 2890 return 2891 } 2892 defer res.Body.Close() 2893 2894 want := []string{ 2895 // Because Request.ContentLength = 0, the body is sniffed for 1 byte to determine whether there's content. 2896 // That explains the initial "num0" being split into "n" and "um0". 2897 // The first byte is included with the request headers Write. Perhaps in the future 2898 // we will want to flush the headers out early if the first byte of the request body is 2899 // taking a long time to arrive. But not yet. 2900 "POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n" + 2901 "1\r\nn\r\n", 2902 "4\r\num0\n\r\n", 2903 "5\r\nnum1\n\r\n", 2904 "5\r\nnum2\n\r\n", 2905 "0\r\n\r\n", 2906 } 2907 if !reflect.DeepEqual(lw.writes, want) { 2908 t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want) 2909 } 2910 } 2911 2912 // Issue 11745. 2913 func TestTransportPrefersResponseOverWriteError(t *testing.T) { 2914 if testing.Short() { 2915 t.Skip("skipping in short mode") 2916 } 2917 defer afterTest(t) 2918 const contentLengthLimit = 1024 * 1024 // 1MB 2919 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2920 if r.ContentLength >= contentLengthLimit { 2921 w.WriteHeader(StatusBadRequest) 2922 r.Body.Close() 2923 return 2924 } 2925 w.WriteHeader(StatusOK) 2926 })) 2927 defer ts.Close() 2928 2929 fail := 0 2930 count := 100 2931 bigBody := strings.Repeat("a", contentLengthLimit*2) 2932 for i := 0; i < count; i++ { 2933 req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody)) 2934 if err != nil { 2935 t.Fatal(err) 2936 } 2937 tr := new(Transport) 2938 defer tr.CloseIdleConnections() 2939 client := &Client{Transport: tr} 2940 resp, err := client.Do(req) 2941 if err != nil { 2942 fail++ 2943 t.Logf("%d = %#v", i, err) 2944 if ue, ok := err.(*url.Error); ok { 2945 t.Logf("urlErr = %#v", ue.Err) 2946 if ne, ok := ue.Err.(*net.OpError); ok { 2947 t.Logf("netOpError = %#v", ne.Err) 2948 } 2949 } 2950 } else { 2951 resp.Body.Close() 2952 if resp.StatusCode != 400 { 2953 t.Errorf("Expected status code 400, got %v", resp.Status) 2954 } 2955 } 2956 } 2957 if fail > 0 { 2958 t.Errorf("Failed %v out of %v\n", fail, count) 2959 } 2960 } 2961 2962 func TestTransportAutomaticHTTP2(t *testing.T) { 2963 testTransportAutoHTTP(t, &Transport{}, true) 2964 } 2965 2966 // golang.org/issue/14391: also check DefaultTransport 2967 func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) { 2968 testTransportAutoHTTP(t, DefaultTransport.(*Transport), true) 2969 } 2970 2971 func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { 2972 testTransportAutoHTTP(t, &Transport{ 2973 TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), 2974 }, false) 2975 } 2976 2977 func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { 2978 testTransportAutoHTTP(t, &Transport{ 2979 TLSClientConfig: new(tls.Config), 2980 }, false) 2981 } 2982 2983 func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { 2984 testTransportAutoHTTP(t, &Transport{ 2985 ExpectContinueTimeout: 1 * time.Second, 2986 }, true) 2987 } 2988 2989 func TestTransportAutomaticHTTP2_Dial(t *testing.T) { 2990 var d net.Dialer 2991 testTransportAutoHTTP(t, &Transport{ 2992 Dial: d.Dial, 2993 }, false) 2994 } 2995 2996 func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) { 2997 testTransportAutoHTTP(t, &Transport{ 2998 DialTLS: func(network, addr string) (net.Conn, error) { 2999 panic("unused") 3000 }, 3001 }, false) 3002 } 3003 3004 func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { 3005 _, err := tr.RoundTrip(new(Request)) 3006 if err == nil { 3007 t.Error("expected error from RoundTrip") 3008 } 3009 if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { 3010 t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) 3011 } 3012 } 3013 3014 // Issue 13633: there was a race where we returned bodyless responses 3015 // to callers before recycling the persistent connection, which meant 3016 // a client doing two subsequent requests could end up on different 3017 // connections. It's somewhat harmless but enough tests assume it's 3018 // not true in order to test other things that it's worth fixing. 3019 // Plus it's nice to be consistent and not have timing-dependent 3020 // behavior. 3021 func TestTransportReuseConnEmptyResponseBody(t *testing.T) { 3022 defer afterTest(t) 3023 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3024 w.Header().Set("X-Addr", r.RemoteAddr) 3025 // Empty response body. 3026 })) 3027 defer cst.close() 3028 n := 100 3029 if testing.Short() { 3030 n = 10 3031 } 3032 var firstAddr string 3033 for i := 0; i < n; i++ { 3034 res, err := cst.c.Get(cst.ts.URL) 3035 if err != nil { 3036 log.Fatal(err) 3037 } 3038 addr := res.Header.Get("X-Addr") 3039 if i == 0 { 3040 firstAddr = addr 3041 } else if addr != firstAddr { 3042 t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr) 3043 } 3044 res.Body.Close() 3045 } 3046 } 3047 3048 // Issue 13839 3049 func TestNoCrashReturningTransportAltConn(t *testing.T) { 3050 cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) 3051 if err != nil { 3052 t.Fatal(err) 3053 } 3054 ln := newLocalListener(t) 3055 defer ln.Close() 3056 3057 handledPendingDial := make(chan bool, 1) 3058 SetPendingDialHooks(nil, func() { handledPendingDial <- true }) 3059 defer SetPendingDialHooks(nil, nil) 3060 3061 testDone := make(chan struct{}) 3062 defer close(testDone) 3063 go func() { 3064 tln := tls.NewListener(ln, &tls.Config{ 3065 NextProtos: []string{"foo"}, 3066 Certificates: []tls.Certificate{cert}, 3067 }) 3068 sc, err := tln.Accept() 3069 if err != nil { 3070 t.Error(err) 3071 return 3072 } 3073 if err := sc.(*tls.Conn).Handshake(); err != nil { 3074 t.Error(err) 3075 return 3076 } 3077 <-testDone 3078 sc.Close() 3079 }() 3080 3081 addr := ln.Addr().String() 3082 3083 req, _ := NewRequest("GET", "https://fake.tld/", nil) 3084 cancel := make(chan struct{}) 3085 req.Cancel = cancel 3086 3087 doReturned := make(chan bool, 1) 3088 madeRoundTripper := make(chan bool, 1) 3089 3090 tr := &Transport{ 3091 DisableKeepAlives: true, 3092 TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{ 3093 "foo": func(authority string, c *tls.Conn) RoundTripper { 3094 madeRoundTripper <- true 3095 return funcRoundTripper(func() { 3096 t.Error("foo RoundTripper should not be called") 3097 }) 3098 }, 3099 }, 3100 Dial: func(_, _ string) (net.Conn, error) { 3101 panic("shouldn't be called") 3102 }, 3103 DialTLS: func(_, _ string) (net.Conn, error) { 3104 tc, err := tls.Dial("tcp", addr, &tls.Config{ 3105 InsecureSkipVerify: true, 3106 NextProtos: []string{"foo"}, 3107 }) 3108 if err != nil { 3109 return nil, err 3110 } 3111 if err := tc.Handshake(); err != nil { 3112 return nil, err 3113 } 3114 close(cancel) 3115 <-doReturned 3116 return tc, nil 3117 }, 3118 } 3119 c := &Client{Transport: tr} 3120 3121 _, err = c.Do(req) 3122 if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn { 3123 t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err) 3124 } 3125 3126 doReturned <- true 3127 <-madeRoundTripper 3128 <-handledPendingDial 3129 } 3130 3131 func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) { 3132 testTransportReuseConnection_Gzip(t, true) 3133 } 3134 3135 func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) { 3136 testTransportReuseConnection_Gzip(t, false) 3137 } 3138 3139 // Make sure we re-use underlying TCP connection for gzipped responses too. 3140 func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) { 3141 defer afterTest(t) 3142 addr := make(chan string, 2) 3143 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3144 addr <- r.RemoteAddr 3145 w.Header().Set("Content-Encoding", "gzip") 3146 if chunked { 3147 w.(Flusher).Flush() 3148 } 3149 w.Write(rgz) // arbitrary gzip response 3150 })) 3151 defer ts.Close() 3152 3153 tr := &Transport{} 3154 defer tr.CloseIdleConnections() 3155 c := &Client{Transport: tr} 3156 for i := 0; i < 2; i++ { 3157 res, err := c.Get(ts.URL) 3158 if err != nil { 3159 t.Fatal(err) 3160 } 3161 buf := make([]byte, len(rgz)) 3162 if n, err := io.ReadFull(res.Body, buf); err != nil { 3163 t.Errorf("%d. ReadFull = %v, %v", i, n, err) 3164 } 3165 // Note: no res.Body.Close call. It should work without it, 3166 // since the flate.Reader's internal buffering will hit EOF 3167 // and that should be sufficient. 3168 } 3169 a1, a2 := <-addr, <-addr 3170 if a1 != a2 { 3171 t.Fatalf("didn't reuse connection") 3172 } 3173 } 3174 3175 func TestTransportResponseHeaderLength(t *testing.T) { 3176 defer afterTest(t) 3177 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3178 if r.URL.Path == "/long" { 3179 w.Header().Set("Long", strings.Repeat("a", 1<<20)) 3180 } 3181 })) 3182 defer ts.Close() 3183 3184 tr := &Transport{ 3185 MaxResponseHeaderBytes: 512 << 10, 3186 } 3187 defer tr.CloseIdleConnections() 3188 c := &Client{Transport: tr} 3189 if res, err := c.Get(ts.URL); err != nil { 3190 t.Fatal(err) 3191 } else { 3192 res.Body.Close() 3193 } 3194 3195 res, err := c.Get(ts.URL + "/long") 3196 if err == nil { 3197 defer res.Body.Close() 3198 var n int64 3199 for k, vv := range res.Header { 3200 for _, v := range vv { 3201 n += int64(len(k)) + int64(len(v)) 3202 } 3203 } 3204 t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n) 3205 } 3206 if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) { 3207 t.Errorf("got error: %v; want %q", err, want) 3208 } 3209 } 3210 3211 func TestTransportEventTrace(t *testing.T) { testTransportEventTrace(t, h1Mode, false) } 3212 func TestTransportEventTrace_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, false) } 3213 3214 // test a non-nil httptrace.ClientTrace but with all hooks set to zero. 3215 func TestTransportEventTrace_NoHooks(t *testing.T) { testTransportEventTrace(t, h1Mode, true) } 3216 func TestTransportEventTrace_NoHooks_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, true) } 3217 3218 func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { 3219 defer afterTest(t) 3220 const resBody = "some body" 3221 gotWroteReqEvent := make(chan struct{}) 3222 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3223 if _, err := ioutil.ReadAll(r.Body); err != nil { 3224 t.Error(err) 3225 } 3226 if !noHooks { 3227 select { 3228 case <-gotWroteReqEvent: 3229 case <-time.After(5 * time.Second): 3230 t.Error("timeout waiting for WroteRequest event") 3231 } 3232 } 3233 io.WriteString(w, resBody) 3234 })) 3235 defer cst.close() 3236 3237 cst.tr.ExpectContinueTimeout = 1 * time.Second 3238 3239 var mu sync.Mutex 3240 var buf bytes.Buffer 3241 logf := func(format string, args ...interface{}) { 3242 mu.Lock() 3243 defer mu.Unlock() 3244 fmt.Fprintf(&buf, format, args...) 3245 buf.WriteByte('\n') 3246 } 3247 3248 addrStr := cst.ts.Listener.Addr().String() 3249 ip, port, err := net.SplitHostPort(addrStr) 3250 if err != nil { 3251 t.Fatal(err) 3252 } 3253 3254 // Install a fake DNS server. 3255 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3256 if host != "dns-is-faked.golang" { 3257 t.Errorf("unexpected DNS host lookup for %q", host) 3258 return nil, nil 3259 } 3260 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3261 }) 3262 3263 req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader("some body")) 3264 trace := &httptrace.ClientTrace{ 3265 GetConn: func(hostPort string) { logf("Getting conn for %v ...", hostPort) }, 3266 GotConn: func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) }, 3267 GotFirstResponseByte: func() { logf("first response byte") }, 3268 PutIdleConn: func(err error) { logf("PutIdleConn = %v", err) }, 3269 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) }, 3270 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) }, 3271 ConnectStart: func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) }, 3272 ConnectDone: func(network, addr string, err error) { 3273 if err != nil { 3274 t.Errorf("ConnectDone: %v", err) 3275 } 3276 logf("ConnectDone: connected to %s %s = %v", network, addr, err) 3277 }, 3278 Wait100Continue: func() { logf("Wait100Continue") }, 3279 Got100Continue: func() { logf("Got100Continue") }, 3280 WroteRequest: func(e httptrace.WroteRequestInfo) { 3281 close(gotWroteReqEvent) 3282 logf("WroteRequest: %+v", e) 3283 }, 3284 } 3285 if noHooks { 3286 // zero out all func pointers, trying to get some path to crash 3287 *trace = httptrace.ClientTrace{} 3288 } 3289 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 3290 3291 req.Header.Set("Expect", "100-continue") 3292 res, err := cst.c.Do(req) 3293 if err != nil { 3294 t.Fatal(err) 3295 } 3296 logf("got roundtrip.response") 3297 slurp, err := ioutil.ReadAll(res.Body) 3298 if err != nil { 3299 t.Fatal(err) 3300 } 3301 logf("consumed body") 3302 if string(slurp) != resBody || res.StatusCode != 200 { 3303 t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody) 3304 } 3305 res.Body.Close() 3306 3307 if noHooks { 3308 // Done at this point. Just testing a full HTTP 3309 // requests can happen with a trace pointing to a zero 3310 // ClientTrace, full of nil func pointers. 3311 return 3312 } 3313 3314 got := buf.String() 3315 wantOnce := func(sub string) { 3316 if strings.Count(got, sub) != 1 { 3317 t.Errorf("expected substring %q exactly once in output.", sub) 3318 } 3319 } 3320 wantOnceOrMore := func(sub string) { 3321 if strings.Count(got, sub) == 0 { 3322 t.Errorf("expected substring %q at least once in output.", sub) 3323 } 3324 } 3325 wantOnce("Getting conn for dns-is-faked.golang:" + port) 3326 wantOnce("DNS start: {Host:dns-is-faked.golang}") 3327 wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}") 3328 wantOnce("got conn: {") 3329 wantOnceOrMore("Connecting to tcp " + addrStr) 3330 wantOnceOrMore("connected to tcp " + addrStr + " = <nil>") 3331 wantOnce("Reused:false WasIdle:false IdleTime:0s") 3332 wantOnce("first response byte") 3333 if !h2 { 3334 wantOnce("PutIdleConn = <nil>") 3335 } 3336 wantOnce("Wait100Continue") 3337 wantOnce("Got100Continue") 3338 wantOnce("WroteRequest: {Err:<nil>}") 3339 if strings.Contains(got, " to udp ") { 3340 t.Errorf("should not see UDP (DNS) connections") 3341 } 3342 if t.Failed() { 3343 t.Errorf("Output:\n%s", got) 3344 } 3345 } 3346 3347 func TestTransportEventTraceRealDNS(t *testing.T) { 3348 defer afterTest(t) 3349 tr := &Transport{} 3350 defer tr.CloseIdleConnections() 3351 c := &Client{Transport: tr} 3352 3353 var mu sync.Mutex 3354 var buf bytes.Buffer 3355 logf := func(format string, args ...interface{}) { 3356 mu.Lock() 3357 defer mu.Unlock() 3358 fmt.Fprintf(&buf, format, args...) 3359 buf.WriteByte('\n') 3360 } 3361 3362 req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil) 3363 trace := &httptrace.ClientTrace{ 3364 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) }, 3365 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) }, 3366 ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) }, 3367 ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) }, 3368 } 3369 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 3370 3371 resp, err := c.Do(req) 3372 if err == nil { 3373 resp.Body.Close() 3374 t.Fatal("expected error during DNS lookup") 3375 } 3376 3377 got := buf.String() 3378 wantSub := func(sub string) { 3379 if !strings.Contains(got, sub) { 3380 t.Errorf("expected substring %q in output.", sub) 3381 } 3382 } 3383 wantSub("DNSStart: {Host:dns-should-not-resolve.golang}") 3384 wantSub("DNSDone: {Addrs:[] Err:") 3385 if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") { 3386 t.Errorf("should not see Connect events") 3387 } 3388 if t.Failed() { 3389 t.Errorf("Output:\n%s", got) 3390 } 3391 } 3392 3393 func TestTransportMaxIdleConns(t *testing.T) { 3394 defer afterTest(t) 3395 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3396 // No body for convenience. 3397 })) 3398 defer ts.Close() 3399 tr := &Transport{ 3400 MaxIdleConns: 4, 3401 } 3402 defer tr.CloseIdleConnections() 3403 3404 ip, port, err := net.SplitHostPort(ts.Listener.Addr().String()) 3405 if err != nil { 3406 t.Fatal(err) 3407 } 3408 c := &Client{Transport: tr} 3409 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3410 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3411 }) 3412 3413 hitHost := func(n int) { 3414 req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil) 3415 req = req.WithContext(ctx) 3416 res, err := c.Do(req) 3417 if err != nil { 3418 t.Fatal(err) 3419 } 3420 res.Body.Close() 3421 } 3422 for i := 0; i < 4; i++ { 3423 hitHost(i) 3424 } 3425 want := []string{ 3426 "|http|host-0.dns-is-faked.golang:" + port, 3427 "|http|host-1.dns-is-faked.golang:" + port, 3428 "|http|host-2.dns-is-faked.golang:" + port, 3429 "|http|host-3.dns-is-faked.golang:" + port, 3430 } 3431 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3432 t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want) 3433 } 3434 3435 // Now hitting the 5th host should kick out the first host: 3436 hitHost(4) 3437 want = []string{ 3438 "|http|host-1.dns-is-faked.golang:" + port, 3439 "|http|host-2.dns-is-faked.golang:" + port, 3440 "|http|host-3.dns-is-faked.golang:" + port, 3441 "|http|host-4.dns-is-faked.golang:" + port, 3442 } 3443 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3444 t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want) 3445 } 3446 } 3447 3448 func TestTransportIdleConnTimeout(t *testing.T) { 3449 if testing.Short() { 3450 t.Skip("skipping in short mode") 3451 } 3452 defer afterTest(t) 3453 3454 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3455 // No body for convenience. 3456 })) 3457 defer ts.Close() 3458 3459 const timeout = 1 * time.Second 3460 tr := &Transport{ 3461 IdleConnTimeout: timeout, 3462 } 3463 defer tr.CloseIdleConnections() 3464 c := &Client{Transport: tr} 3465 3466 var conn string 3467 doReq := func(n int) { 3468 req, _ := NewRequest("GET", ts.URL, nil) 3469 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 3470 PutIdleConn: func(err error) { 3471 if err != nil { 3472 t.Errorf("failed to keep idle conn: %v", err) 3473 } 3474 }, 3475 })) 3476 res, err := c.Do(req) 3477 if err != nil { 3478 t.Fatal(err) 3479 } 3480 res.Body.Close() 3481 conns := tr.IdleConnStrsForTesting() 3482 if len(conns) != 1 { 3483 t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns) 3484 } 3485 if conn == "" { 3486 conn = conns[0] 3487 } 3488 if conn != conns[0] { 3489 t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n) 3490 } 3491 } 3492 for i := 0; i < 3; i++ { 3493 doReq(i) 3494 time.Sleep(timeout / 2) 3495 } 3496 time.Sleep(timeout * 3 / 2) 3497 if got := tr.IdleConnStrsForTesting(); len(got) != 0 { 3498 t.Errorf("idle conns = %q; want none", got) 3499 } 3500 } 3501 3502 var errFakeRoundTrip = errors.New("fake roundtrip") 3503 3504 type funcRoundTripper func() 3505 3506 func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) { 3507 fn() 3508 return nil, errFakeRoundTrip 3509 } 3510 3511 func wantBody(res *Response, err error, want string) error { 3512 if err != nil { 3513 return err 3514 } 3515 slurp, err := ioutil.ReadAll(res.Body) 3516 if err != nil { 3517 return fmt.Errorf("error reading body: %v", err) 3518 } 3519 if string(slurp) != want { 3520 return fmt.Errorf("body = %q; want %q", slurp, want) 3521 } 3522 if err := res.Body.Close(); err != nil { 3523 return fmt.Errorf("body Close = %v", err) 3524 } 3525 return nil 3526 } 3527 3528 func newLocalListener(t *testing.T) net.Listener { 3529 ln, err := net.Listen("tcp", "127.0.0.1:0") 3530 if err != nil { 3531 ln, err = net.Listen("tcp6", "[::1]:0") 3532 } 3533 if err != nil { 3534 t.Fatal(err) 3535 } 3536 return ln 3537 } 3538 3539 type countCloseReader struct { 3540 n *int 3541 io.Reader 3542 } 3543 3544 func (cr countCloseReader) Close() error { 3545 (*cr.n)++ 3546 return nil 3547 } 3548 3549 // rgz is a gzip quine that uncompresses to itself. 3550 var rgz = []byte{ 3551 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 3552 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 3553 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 3554 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 3555 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 3556 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 3557 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 3558 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 3559 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 3560 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 3561 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 3562 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 3563 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 3564 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 3565 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 3566 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 3567 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 3568 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 3569 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 3570 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 3571 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 3572 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 3573 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 3574 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 3575 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 3576 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 3577 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 3578 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 3579 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 3580 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 3581 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 3582 0x00, 0x00, 3583 }