github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/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_PROXY 2064 reqmeth string // REQUEST_METHOD 2065 2066 want string 2067 wanterr error 2068 } 2069 2070 func (t proxyFromEnvTest) String() string { 2071 var buf bytes.Buffer 2072 space := func() { 2073 if buf.Len() > 0 { 2074 buf.WriteByte(' ') 2075 } 2076 } 2077 if t.env != "" { 2078 fmt.Fprintf(&buf, "http_proxy=%q", t.env) 2079 } 2080 if t.httpsenv != "" { 2081 space() 2082 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv) 2083 } 2084 if t.noenv != "" { 2085 space() 2086 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv) 2087 } 2088 if t.reqmeth != "" { 2089 space() 2090 fmt.Fprintf(&buf, "request_method=%q", t.reqmeth) 2091 } 2092 req := "http://example.com" 2093 if t.req != "" { 2094 req = t.req 2095 } 2096 space() 2097 fmt.Fprintf(&buf, "req=%q", req) 2098 return strings.TrimSpace(buf.String()) 2099 } 2100 2101 var proxyFromEnvTests = []proxyFromEnvTest{ 2102 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2103 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"}, 2104 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"}, 2105 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"}, 2106 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2107 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"}, 2108 2109 // Don't use secure for http 2110 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"}, 2111 // Use secure for https. 2112 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"}, 2113 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"}, 2114 2115 // Issue 16405: don't use HTTP_PROXY in a CGI environment, 2116 // where HTTP_PROXY can be attacker-controlled. 2117 {env: "http://10.1.2.3:8080", reqmeth: "POST", 2118 want: "<nil>", 2119 wanterr: errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")}, 2120 2121 {want: "<nil>"}, 2122 2123 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2124 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2125 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2126 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"}, 2127 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2128 } 2129 2130 func TestProxyFromEnvironment(t *testing.T) { 2131 ResetProxyEnv() 2132 for _, tt := range proxyFromEnvTests { 2133 os.Setenv("HTTP_PROXY", tt.env) 2134 os.Setenv("HTTPS_PROXY", tt.httpsenv) 2135 os.Setenv("NO_PROXY", tt.noenv) 2136 os.Setenv("REQUEST_METHOD", tt.reqmeth) 2137 ResetCachedEnvironment() 2138 reqURL := tt.req 2139 if reqURL == "" { 2140 reqURL = "http://example.com" 2141 } 2142 req, _ := NewRequest("GET", reqURL, nil) 2143 url, err := ProxyFromEnvironment(req) 2144 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 2145 t.Errorf("%v: got error = %q, want %q", tt, g, e) 2146 continue 2147 } 2148 if got := fmt.Sprintf("%s", url); got != tt.want { 2149 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 2150 } 2151 } 2152 } 2153 2154 func TestIdleConnChannelLeak(t *testing.T) { 2155 var mu sync.Mutex 2156 var n int 2157 2158 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2159 mu.Lock() 2160 n++ 2161 mu.Unlock() 2162 })) 2163 defer ts.Close() 2164 2165 const nReqs = 5 2166 didRead := make(chan bool, nReqs) 2167 SetReadLoopBeforeNextReadHook(func() { didRead <- true }) 2168 defer SetReadLoopBeforeNextReadHook(nil) 2169 2170 tr := &Transport{ 2171 Dial: func(netw, addr string) (net.Conn, error) { 2172 return net.Dial(netw, ts.Listener.Addr().String()) 2173 }, 2174 } 2175 defer tr.CloseIdleConnections() 2176 2177 c := &Client{Transport: tr} 2178 2179 // First, without keep-alives. 2180 for _, disableKeep := range []bool{true, false} { 2181 tr.DisableKeepAlives = disableKeep 2182 for i := 0; i < nReqs; i++ { 2183 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i)) 2184 if err != nil { 2185 t.Fatal(err) 2186 } 2187 // Note: no res.Body.Close is needed here, since the 2188 // response Content-Length is zero. Perhaps the test 2189 // should be more explicit and use a HEAD, but tests 2190 // elsewhere guarantee that zero byte responses generate 2191 // a "Content-Length: 0" instead of chunking. 2192 } 2193 2194 // At this point, each of the 5 Transport.readLoop goroutines 2195 // are scheduling noting that there are no response bodies (see 2196 // earlier comment), and are then calling putIdleConn, which 2197 // decrements this count. Usually that happens quickly, which is 2198 // why this test has seemed to work for ages. But it's still 2199 // racey: we have wait for them to finish first. See Issue 10427 2200 for i := 0; i < nReqs; i++ { 2201 <-didRead 2202 } 2203 2204 if got := tr.IdleConnChMapSizeForTesting(); got != 0 { 2205 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got) 2206 } 2207 } 2208 } 2209 2210 // Verify the status quo: that the Client.Post function coerces its 2211 // body into a ReadCloser if it's a Closer, and that the Transport 2212 // then closes it. 2213 func TestTransportClosesRequestBody(t *testing.T) { 2214 defer afterTest(t) 2215 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2216 io.Copy(ioutil.Discard, r.Body) 2217 })) 2218 defer ts.Close() 2219 2220 tr := &Transport{} 2221 defer tr.CloseIdleConnections() 2222 cl := &Client{Transport: tr} 2223 2224 closes := 0 2225 2226 res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")}) 2227 if err != nil { 2228 t.Fatal(err) 2229 } 2230 res.Body.Close() 2231 if closes != 1 { 2232 t.Errorf("closes = %d; want 1", closes) 2233 } 2234 } 2235 2236 func TestTransportTLSHandshakeTimeout(t *testing.T) { 2237 defer afterTest(t) 2238 if testing.Short() { 2239 t.Skip("skipping in short mode") 2240 } 2241 ln := newLocalListener(t) 2242 defer ln.Close() 2243 testdonec := make(chan struct{}) 2244 defer close(testdonec) 2245 2246 go func() { 2247 c, err := ln.Accept() 2248 if err != nil { 2249 t.Error(err) 2250 return 2251 } 2252 <-testdonec 2253 c.Close() 2254 }() 2255 2256 getdonec := make(chan struct{}) 2257 go func() { 2258 defer close(getdonec) 2259 tr := &Transport{ 2260 Dial: func(_, _ string) (net.Conn, error) { 2261 return net.Dial("tcp", ln.Addr().String()) 2262 }, 2263 TLSHandshakeTimeout: 250 * time.Millisecond, 2264 } 2265 cl := &Client{Transport: tr} 2266 _, err := cl.Get("https://dummy.tld/") 2267 if err == nil { 2268 t.Error("expected error") 2269 return 2270 } 2271 ue, ok := err.(*url.Error) 2272 if !ok { 2273 t.Errorf("expected url.Error; got %#v", err) 2274 return 2275 } 2276 ne, ok := ue.Err.(net.Error) 2277 if !ok { 2278 t.Errorf("expected net.Error; got %#v", err) 2279 return 2280 } 2281 if !ne.Timeout() { 2282 t.Errorf("expected timeout error; got %v", err) 2283 } 2284 if !strings.Contains(err.Error(), "handshake timeout") { 2285 t.Errorf("expected 'handshake timeout' in error; got %v", err) 2286 } 2287 }() 2288 select { 2289 case <-getdonec: 2290 case <-time.After(5 * time.Second): 2291 t.Error("test timeout; TLS handshake hung?") 2292 } 2293 } 2294 2295 // Trying to repro golang.org/issue/3514 2296 func TestTLSServerClosesConnection(t *testing.T) { 2297 defer afterTest(t) 2298 testenv.SkipFlaky(t, 7634) 2299 2300 closedc := make(chan bool, 1) 2301 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2302 if strings.Contains(r.URL.Path, "/keep-alive-then-die") { 2303 conn, _, _ := w.(Hijacker).Hijack() 2304 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) 2305 conn.Close() 2306 closedc <- true 2307 return 2308 } 2309 fmt.Fprintf(w, "hello") 2310 })) 2311 defer ts.Close() 2312 tr := &Transport{ 2313 TLSClientConfig: &tls.Config{ 2314 InsecureSkipVerify: true, 2315 }, 2316 } 2317 defer tr.CloseIdleConnections() 2318 client := &Client{Transport: tr} 2319 2320 var nSuccess = 0 2321 var errs []error 2322 const trials = 20 2323 for i := 0; i < trials; i++ { 2324 tr.CloseIdleConnections() 2325 res, err := client.Get(ts.URL + "/keep-alive-then-die") 2326 if err != nil { 2327 t.Fatal(err) 2328 } 2329 <-closedc 2330 slurp, err := ioutil.ReadAll(res.Body) 2331 if err != nil { 2332 t.Fatal(err) 2333 } 2334 if string(slurp) != "foo" { 2335 t.Errorf("Got %q, want foo", slurp) 2336 } 2337 2338 // Now try again and see if we successfully 2339 // pick a new connection. 2340 res, err = client.Get(ts.URL + "/") 2341 if err != nil { 2342 errs = append(errs, err) 2343 continue 2344 } 2345 slurp, err = ioutil.ReadAll(res.Body) 2346 if err != nil { 2347 errs = append(errs, err) 2348 continue 2349 } 2350 nSuccess++ 2351 } 2352 if nSuccess > 0 { 2353 t.Logf("successes = %d of %d", nSuccess, trials) 2354 } else { 2355 t.Errorf("All runs failed:") 2356 } 2357 for _, err := range errs { 2358 t.Logf(" err: %v", err) 2359 } 2360 } 2361 2362 // byteFromChanReader is an io.Reader that reads a single byte at a 2363 // time from the channel. When the channel is closed, the reader 2364 // returns io.EOF. 2365 type byteFromChanReader chan byte 2366 2367 func (c byteFromChanReader) Read(p []byte) (n int, err error) { 2368 if len(p) == 0 { 2369 return 2370 } 2371 b, ok := <-c 2372 if !ok { 2373 return 0, io.EOF 2374 } 2375 p[0] = b 2376 return 1, nil 2377 } 2378 2379 // Verifies that the Transport doesn't reuse a connection in the case 2380 // where the server replies before the request has been fully 2381 // written. We still honor that reply (see TestIssue3595), but don't 2382 // send future requests on the connection because it's then in a 2383 // questionable state. 2384 // golang.org/issue/7569 2385 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) { 2386 defer afterTest(t) 2387 var sconn struct { 2388 sync.Mutex 2389 c net.Conn 2390 } 2391 var getOkay bool 2392 closeConn := func() { 2393 sconn.Lock() 2394 defer sconn.Unlock() 2395 if sconn.c != nil { 2396 sconn.c.Close() 2397 sconn.c = nil 2398 if !getOkay { 2399 t.Logf("Closed server connection") 2400 } 2401 } 2402 } 2403 defer closeConn() 2404 2405 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2406 if r.Method == "GET" { 2407 io.WriteString(w, "bar") 2408 return 2409 } 2410 conn, _, _ := w.(Hijacker).Hijack() 2411 sconn.Lock() 2412 sconn.c = conn 2413 sconn.Unlock() 2414 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive 2415 go io.Copy(ioutil.Discard, conn) 2416 })) 2417 defer ts.Close() 2418 tr := &Transport{} 2419 defer tr.CloseIdleConnections() 2420 client := &Client{Transport: tr} 2421 2422 const bodySize = 256 << 10 2423 finalBit := make(byteFromChanReader, 1) 2424 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit)) 2425 req.ContentLength = bodySize 2426 res, err := client.Do(req) 2427 if err := wantBody(res, err, "foo"); err != nil { 2428 t.Errorf("POST response: %v", err) 2429 } 2430 donec := make(chan bool) 2431 go func() { 2432 defer close(donec) 2433 res, err = client.Get(ts.URL) 2434 if err := wantBody(res, err, "bar"); err != nil { 2435 t.Errorf("GET response: %v", err) 2436 return 2437 } 2438 getOkay = true // suppress test noise 2439 }() 2440 time.AfterFunc(5*time.Second, closeConn) 2441 select { 2442 case <-donec: 2443 finalBit <- 'x' // unblock the writeloop of the first Post 2444 close(finalBit) 2445 case <-time.After(7 * time.Second): 2446 t.Fatal("timeout waiting for GET request to finish") 2447 } 2448 } 2449 2450 // Tests that we don't leak Transport persistConn.readLoop goroutines 2451 // when a server hangs up immediately after saying it would keep-alive. 2452 func TestTransportIssue10457(t *testing.T) { 2453 defer afterTest(t) // used to fail in goroutine leak check 2454 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2455 // Send a response with no body, keep-alive 2456 // (implicit), and then lie and immediately close the 2457 // connection. This forces the Transport's readLoop to 2458 // immediately Peek an io.EOF and get to the point 2459 // that used to hang. 2460 conn, _, _ := w.(Hijacker).Hijack() 2461 conn.Write([]byte("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 0\r\n\r\n")) // keep-alive 2462 conn.Close() 2463 })) 2464 defer ts.Close() 2465 tr := &Transport{} 2466 defer tr.CloseIdleConnections() 2467 cl := &Client{Transport: tr} 2468 res, err := cl.Get(ts.URL) 2469 if err != nil { 2470 t.Fatalf("Get: %v", err) 2471 } 2472 defer res.Body.Close() 2473 2474 // Just a sanity check that we at least get the response. The real 2475 // test here is that the "defer afterTest" above doesn't find any 2476 // leaked goroutines. 2477 if got, want := res.Header.Get("Foo"), "Bar"; got != want { 2478 t.Errorf("Foo header = %q; want %q", got, want) 2479 } 2480 } 2481 2482 type errorReader struct { 2483 err error 2484 } 2485 2486 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err } 2487 2488 type plan9SleepReader struct{} 2489 2490 func (plan9SleepReader) Read(p []byte) (int, error) { 2491 if runtime.GOOS == "plan9" { 2492 // After the fix to unblock TCP Reads in 2493 // https://golang.org/cl/15941, this sleep is required 2494 // on plan9 to make sure TCP Writes before an 2495 // immediate TCP close go out on the wire. On Plan 9, 2496 // it seems that a hangup of a TCP connection with 2497 // queued data doesn't send the queued data first. 2498 // https://golang.org/issue/9554 2499 time.Sleep(50 * time.Millisecond) 2500 } 2501 return 0, io.EOF 2502 } 2503 2504 type closerFunc func() error 2505 2506 func (f closerFunc) Close() error { return f() } 2507 2508 // Issue 4677. If we try to reuse a connection that the server is in the 2509 // process of closing, we may end up successfully writing out our request (or a 2510 // portion of our request) only to find a connection error when we try to read 2511 // from (or finish writing to) the socket. 2512 // 2513 // NOTE: we resend a request only if the request is idempotent, we reused a 2514 // keep-alive connection, and we haven't yet received any header data. This 2515 // automatically prevents an infinite resend loop because we'll run out of the 2516 // cached keep-alive connections eventually. 2517 func TestRetryIdempotentRequestsOnError(t *testing.T) { 2518 defer afterTest(t) 2519 2520 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2521 })) 2522 defer ts.Close() 2523 2524 tr := &Transport{} 2525 c := &Client{Transport: tr} 2526 2527 const N = 2 2528 retryc := make(chan struct{}, N) 2529 SetRoundTripRetried(func() { 2530 retryc <- struct{}{} 2531 }) 2532 defer SetRoundTripRetried(nil) 2533 2534 for n := 0; n < 100; n++ { 2535 // open 2 conns 2536 errc := make(chan error, N) 2537 for i := 0; i < N; i++ { 2538 // start goroutines, send on errc 2539 go func() { 2540 res, err := c.Get(ts.URL) 2541 if err == nil { 2542 res.Body.Close() 2543 } 2544 errc <- err 2545 }() 2546 } 2547 for i := 0; i < N; i++ { 2548 if err := <-errc; err != nil { 2549 t.Fatal(err) 2550 } 2551 } 2552 2553 ts.CloseClientConnections() 2554 for i := 0; i < N; i++ { 2555 go func() { 2556 res, err := c.Get(ts.URL) 2557 if err == nil { 2558 res.Body.Close() 2559 } 2560 errc <- err 2561 }() 2562 } 2563 2564 for i := 0; i < N; i++ { 2565 if err := <-errc; err != nil { 2566 t.Fatal(err) 2567 } 2568 } 2569 for i := 0; i < N; i++ { 2570 select { 2571 case <-retryc: 2572 // we triggered a retry, test was successful 2573 t.Logf("finished after %d runs\n", n) 2574 return 2575 default: 2576 } 2577 } 2578 } 2579 t.Fatal("did not trigger any retries") 2580 } 2581 2582 // Issue 6981 2583 func TestTransportClosesBodyOnError(t *testing.T) { 2584 setParallel(t) 2585 defer afterTest(t) 2586 readBody := make(chan error, 1) 2587 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2588 _, err := ioutil.ReadAll(r.Body) 2589 readBody <- err 2590 })) 2591 defer ts.Close() 2592 fakeErr := errors.New("fake error") 2593 didClose := make(chan bool, 1) 2594 req, _ := NewRequest("POST", ts.URL, struct { 2595 io.Reader 2596 io.Closer 2597 }{ 2598 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), plan9SleepReader{}, errorReader{fakeErr}), 2599 closerFunc(func() error { 2600 select { 2601 case didClose <- true: 2602 default: 2603 } 2604 return nil 2605 }), 2606 }) 2607 res, err := DefaultClient.Do(req) 2608 if res != nil { 2609 defer res.Body.Close() 2610 } 2611 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 2612 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 2613 } 2614 select { 2615 case err := <-readBody: 2616 if err == nil { 2617 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 2618 } 2619 case <-time.After(5 * time.Second): 2620 t.Error("timeout waiting for server handler to complete") 2621 } 2622 select { 2623 case <-didClose: 2624 default: 2625 t.Errorf("didn't see Body.Close") 2626 } 2627 } 2628 2629 func TestTransportDialTLS(t *testing.T) { 2630 var mu sync.Mutex // guards following 2631 var gotReq, didDial bool 2632 2633 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2634 mu.Lock() 2635 gotReq = true 2636 mu.Unlock() 2637 })) 2638 defer ts.Close() 2639 tr := &Transport{ 2640 DialTLS: func(netw, addr string) (net.Conn, error) { 2641 mu.Lock() 2642 didDial = true 2643 mu.Unlock() 2644 c, err := tls.Dial(netw, addr, &tls.Config{ 2645 InsecureSkipVerify: true, 2646 }) 2647 if err != nil { 2648 return nil, err 2649 } 2650 return c, c.Handshake() 2651 }, 2652 } 2653 defer tr.CloseIdleConnections() 2654 client := &Client{Transport: tr} 2655 res, err := client.Get(ts.URL) 2656 if err != nil { 2657 t.Fatal(err) 2658 } 2659 res.Body.Close() 2660 mu.Lock() 2661 if !gotReq { 2662 t.Error("didn't get request") 2663 } 2664 if !didDial { 2665 t.Error("didn't use dial hook") 2666 } 2667 } 2668 2669 // Test for issue 8755 2670 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 2671 func TestRoundTripReturnsProxyError(t *testing.T) { 2672 badProxy := func(*Request) (*url.URL, error) { 2673 return nil, errors.New("errorMessage") 2674 } 2675 2676 tr := &Transport{Proxy: badProxy} 2677 2678 req, _ := NewRequest("GET", "http://example.com", nil) 2679 2680 _, err := tr.RoundTrip(req) 2681 2682 if err == nil { 2683 t.Error("Expected proxy error to be returned by RoundTrip") 2684 } 2685 } 2686 2687 // tests that putting an idle conn after a call to CloseIdleConns does return it 2688 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 2689 tr := &Transport{} 2690 wantIdle := func(when string, n int) bool { 2691 got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn 2692 if got == n { 2693 return true 2694 } 2695 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 2696 return false 2697 } 2698 wantIdle("start", 0) 2699 if !tr.PutIdleTestConn() { 2700 t.Fatal("put failed") 2701 } 2702 if !tr.PutIdleTestConn() { 2703 t.Fatal("second put failed") 2704 } 2705 wantIdle("after put", 2) 2706 tr.CloseIdleConnections() 2707 if !tr.IsIdleForTesting() { 2708 t.Error("should be idle after CloseIdleConnections") 2709 } 2710 wantIdle("after close idle", 0) 2711 if tr.PutIdleTestConn() { 2712 t.Fatal("put didn't fail") 2713 } 2714 wantIdle("after second put", 0) 2715 2716 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode 2717 if tr.IsIdleForTesting() { 2718 t.Error("shouldn't be idle after RequestIdleConnChForTesting") 2719 } 2720 if !tr.PutIdleTestConn() { 2721 t.Fatal("after re-activation") 2722 } 2723 wantIdle("after final put", 1) 2724 } 2725 2726 // This tests that an client requesting a content range won't also 2727 // implicitly ask for gzip support. If they want that, they need to do it 2728 // on their own. 2729 // golang.org/issue/8923 2730 func TestTransportRangeAndGzip(t *testing.T) { 2731 defer afterTest(t) 2732 reqc := make(chan *Request, 1) 2733 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2734 reqc <- r 2735 })) 2736 defer ts.Close() 2737 2738 req, _ := NewRequest("GET", ts.URL, nil) 2739 req.Header.Set("Range", "bytes=7-11") 2740 res, err := DefaultClient.Do(req) 2741 if err != nil { 2742 t.Fatal(err) 2743 } 2744 2745 select { 2746 case r := <-reqc: 2747 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 2748 t.Error("Transport advertised gzip support in the Accept header") 2749 } 2750 if r.Header.Get("Range") == "" { 2751 t.Error("no Range in request") 2752 } 2753 case <-time.After(10 * time.Second): 2754 t.Fatal("timeout") 2755 } 2756 res.Body.Close() 2757 } 2758 2759 // Test for issue 10474 2760 func TestTransportResponseCancelRace(t *testing.T) { 2761 defer afterTest(t) 2762 2763 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2764 // important that this response has a body. 2765 var b [1024]byte 2766 w.Write(b[:]) 2767 })) 2768 defer ts.Close() 2769 2770 tr := &Transport{} 2771 defer tr.CloseIdleConnections() 2772 2773 req, err := NewRequest("GET", ts.URL, nil) 2774 if err != nil { 2775 t.Fatal(err) 2776 } 2777 res, err := tr.RoundTrip(req) 2778 if err != nil { 2779 t.Fatal(err) 2780 } 2781 // If we do an early close, Transport just throws the connection away and 2782 // doesn't reuse it. In order to trigger the bug, it has to reuse the connection 2783 // so read the body 2784 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { 2785 t.Fatal(err) 2786 } 2787 2788 req2, err := NewRequest("GET", ts.URL, nil) 2789 if err != nil { 2790 t.Fatal(err) 2791 } 2792 tr.CancelRequest(req) 2793 res, err = tr.RoundTrip(req2) 2794 if err != nil { 2795 t.Fatal(err) 2796 } 2797 res.Body.Close() 2798 } 2799 2800 func TestTransportDialCancelRace(t *testing.T) { 2801 defer afterTest(t) 2802 2803 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 2804 defer ts.Close() 2805 2806 tr := &Transport{} 2807 defer tr.CloseIdleConnections() 2808 2809 req, err := NewRequest("GET", ts.URL, nil) 2810 if err != nil { 2811 t.Fatal(err) 2812 } 2813 SetEnterRoundTripHook(func() { 2814 tr.CancelRequest(req) 2815 }) 2816 defer SetEnterRoundTripHook(nil) 2817 res, err := tr.RoundTrip(req) 2818 if err != ExportErrRequestCanceled { 2819 t.Errorf("expected canceled request error; got %v", err) 2820 if err == nil { 2821 res.Body.Close() 2822 } 2823 } 2824 } 2825 2826 // logWritesConn is a net.Conn that logs each Write call to writes 2827 // and then proxies to w. 2828 // It proxies Read calls to a reader it receives from rch. 2829 type logWritesConn struct { 2830 net.Conn // nil. crash on use. 2831 2832 w io.Writer 2833 2834 rch <-chan io.Reader 2835 r io.Reader // nil until received by rch 2836 2837 mu sync.Mutex 2838 writes []string 2839 } 2840 2841 func (c *logWritesConn) Write(p []byte) (n int, err error) { 2842 c.mu.Lock() 2843 defer c.mu.Unlock() 2844 c.writes = append(c.writes, string(p)) 2845 return c.w.Write(p) 2846 } 2847 2848 func (c *logWritesConn) Read(p []byte) (n int, err error) { 2849 if c.r == nil { 2850 c.r = <-c.rch 2851 } 2852 return c.r.Read(p) 2853 } 2854 2855 func (c *logWritesConn) Close() error { return nil } 2856 2857 // Issue 6574 2858 func TestTransportFlushesBodyChunks(t *testing.T) { 2859 defer afterTest(t) 2860 resBody := make(chan io.Reader, 1) 2861 connr, connw := io.Pipe() // connection pipe pair 2862 lw := &logWritesConn{ 2863 rch: resBody, 2864 w: connw, 2865 } 2866 tr := &Transport{ 2867 Dial: func(network, addr string) (net.Conn, error) { 2868 return lw, nil 2869 }, 2870 } 2871 bodyr, bodyw := io.Pipe() // body pipe pair 2872 go func() { 2873 defer bodyw.Close() 2874 for i := 0; i < 3; i++ { 2875 fmt.Fprintf(bodyw, "num%d\n", i) 2876 } 2877 }() 2878 resc := make(chan *Response) 2879 go func() { 2880 req, _ := NewRequest("POST", "http://localhost:8080", bodyr) 2881 req.Header.Set("User-Agent", "x") // known value for test 2882 res, err := tr.RoundTrip(req) 2883 if err != nil { 2884 t.Errorf("RoundTrip: %v", err) 2885 close(resc) 2886 return 2887 } 2888 resc <- res 2889 2890 }() 2891 // Fully consume the request before checking the Write log vs. want. 2892 req, err := ReadRequest(bufio.NewReader(connr)) 2893 if err != nil { 2894 t.Fatal(err) 2895 } 2896 io.Copy(ioutil.Discard, req.Body) 2897 2898 // Unblock the transport's roundTrip goroutine. 2899 resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n") 2900 res, ok := <-resc 2901 if !ok { 2902 return 2903 } 2904 defer res.Body.Close() 2905 2906 want := []string{ 2907 // Because Request.ContentLength = 0, the body is sniffed for 1 byte to determine whether there's content. 2908 // That explains the initial "num0" being split into "n" and "um0". 2909 // The first byte is included with the request headers Write. Perhaps in the future 2910 // we will want to flush the headers out early if the first byte of the request body is 2911 // taking a long time to arrive. But not yet. 2912 "POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n" + 2913 "1\r\nn\r\n", 2914 "4\r\num0\n\r\n", 2915 "5\r\nnum1\n\r\n", 2916 "5\r\nnum2\n\r\n", 2917 "0\r\n\r\n", 2918 } 2919 if !reflect.DeepEqual(lw.writes, want) { 2920 t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want) 2921 } 2922 } 2923 2924 // Issue 11745. 2925 func TestTransportPrefersResponseOverWriteError(t *testing.T) { 2926 if testing.Short() { 2927 t.Skip("skipping in short mode") 2928 } 2929 defer afterTest(t) 2930 const contentLengthLimit = 1024 * 1024 // 1MB 2931 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2932 if r.ContentLength >= contentLengthLimit { 2933 w.WriteHeader(StatusBadRequest) 2934 r.Body.Close() 2935 return 2936 } 2937 w.WriteHeader(StatusOK) 2938 })) 2939 defer ts.Close() 2940 2941 fail := 0 2942 count := 100 2943 bigBody := strings.Repeat("a", contentLengthLimit*2) 2944 for i := 0; i < count; i++ { 2945 req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody)) 2946 if err != nil { 2947 t.Fatal(err) 2948 } 2949 tr := new(Transport) 2950 defer tr.CloseIdleConnections() 2951 client := &Client{Transport: tr} 2952 resp, err := client.Do(req) 2953 if err != nil { 2954 fail++ 2955 t.Logf("%d = %#v", i, err) 2956 if ue, ok := err.(*url.Error); ok { 2957 t.Logf("urlErr = %#v", ue.Err) 2958 if ne, ok := ue.Err.(*net.OpError); ok { 2959 t.Logf("netOpError = %#v", ne.Err) 2960 } 2961 } 2962 } else { 2963 resp.Body.Close() 2964 if resp.StatusCode != 400 { 2965 t.Errorf("Expected status code 400, got %v", resp.Status) 2966 } 2967 } 2968 } 2969 if fail > 0 { 2970 t.Errorf("Failed %v out of %v\n", fail, count) 2971 } 2972 } 2973 2974 func TestTransportAutomaticHTTP2(t *testing.T) { 2975 testTransportAutoHTTP(t, &Transport{}, true) 2976 } 2977 2978 // golang.org/issue/14391: also check DefaultTransport 2979 func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) { 2980 testTransportAutoHTTP(t, DefaultTransport.(*Transport), true) 2981 } 2982 2983 func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { 2984 testTransportAutoHTTP(t, &Transport{ 2985 TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), 2986 }, false) 2987 } 2988 2989 func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { 2990 testTransportAutoHTTP(t, &Transport{ 2991 TLSClientConfig: new(tls.Config), 2992 }, false) 2993 } 2994 2995 func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { 2996 testTransportAutoHTTP(t, &Transport{ 2997 ExpectContinueTimeout: 1 * time.Second, 2998 }, true) 2999 } 3000 3001 func TestTransportAutomaticHTTP2_Dial(t *testing.T) { 3002 var d net.Dialer 3003 testTransportAutoHTTP(t, &Transport{ 3004 Dial: d.Dial, 3005 }, false) 3006 } 3007 3008 func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) { 3009 testTransportAutoHTTP(t, &Transport{ 3010 DialTLS: func(network, addr string) (net.Conn, error) { 3011 panic("unused") 3012 }, 3013 }, false) 3014 } 3015 3016 func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { 3017 _, err := tr.RoundTrip(new(Request)) 3018 if err == nil { 3019 t.Error("expected error from RoundTrip") 3020 } 3021 if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { 3022 t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) 3023 } 3024 } 3025 3026 // Issue 13633: there was a race where we returned bodyless responses 3027 // to callers before recycling the persistent connection, which meant 3028 // a client doing two subsequent requests could end up on different 3029 // connections. It's somewhat harmless but enough tests assume it's 3030 // not true in order to test other things that it's worth fixing. 3031 // Plus it's nice to be consistent and not have timing-dependent 3032 // behavior. 3033 func TestTransportReuseConnEmptyResponseBody(t *testing.T) { 3034 defer afterTest(t) 3035 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3036 w.Header().Set("X-Addr", r.RemoteAddr) 3037 // Empty response body. 3038 })) 3039 defer cst.close() 3040 n := 100 3041 if testing.Short() { 3042 n = 10 3043 } 3044 var firstAddr string 3045 for i := 0; i < n; i++ { 3046 res, err := cst.c.Get(cst.ts.URL) 3047 if err != nil { 3048 log.Fatal(err) 3049 } 3050 addr := res.Header.Get("X-Addr") 3051 if i == 0 { 3052 firstAddr = addr 3053 } else if addr != firstAddr { 3054 t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr) 3055 } 3056 res.Body.Close() 3057 } 3058 } 3059 3060 // Issue 13839 3061 func TestNoCrashReturningTransportAltConn(t *testing.T) { 3062 cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) 3063 if err != nil { 3064 t.Fatal(err) 3065 } 3066 ln := newLocalListener(t) 3067 defer ln.Close() 3068 3069 handledPendingDial := make(chan bool, 1) 3070 SetPendingDialHooks(nil, func() { handledPendingDial <- true }) 3071 defer SetPendingDialHooks(nil, nil) 3072 3073 testDone := make(chan struct{}) 3074 defer close(testDone) 3075 go func() { 3076 tln := tls.NewListener(ln, &tls.Config{ 3077 NextProtos: []string{"foo"}, 3078 Certificates: []tls.Certificate{cert}, 3079 }) 3080 sc, err := tln.Accept() 3081 if err != nil { 3082 t.Error(err) 3083 return 3084 } 3085 if err := sc.(*tls.Conn).Handshake(); err != nil { 3086 t.Error(err) 3087 return 3088 } 3089 <-testDone 3090 sc.Close() 3091 }() 3092 3093 addr := ln.Addr().String() 3094 3095 req, _ := NewRequest("GET", "https://fake.tld/", nil) 3096 cancel := make(chan struct{}) 3097 req.Cancel = cancel 3098 3099 doReturned := make(chan bool, 1) 3100 madeRoundTripper := make(chan bool, 1) 3101 3102 tr := &Transport{ 3103 DisableKeepAlives: true, 3104 TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{ 3105 "foo": func(authority string, c *tls.Conn) RoundTripper { 3106 madeRoundTripper <- true 3107 return funcRoundTripper(func() { 3108 t.Error("foo RoundTripper should not be called") 3109 }) 3110 }, 3111 }, 3112 Dial: func(_, _ string) (net.Conn, error) { 3113 panic("shouldn't be called") 3114 }, 3115 DialTLS: func(_, _ string) (net.Conn, error) { 3116 tc, err := tls.Dial("tcp", addr, &tls.Config{ 3117 InsecureSkipVerify: true, 3118 NextProtos: []string{"foo"}, 3119 }) 3120 if err != nil { 3121 return nil, err 3122 } 3123 if err := tc.Handshake(); err != nil { 3124 return nil, err 3125 } 3126 close(cancel) 3127 <-doReturned 3128 return tc, nil 3129 }, 3130 } 3131 c := &Client{Transport: tr} 3132 3133 _, err = c.Do(req) 3134 if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn { 3135 t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err) 3136 } 3137 3138 doReturned <- true 3139 <-madeRoundTripper 3140 <-handledPendingDial 3141 } 3142 3143 func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) { 3144 testTransportReuseConnection_Gzip(t, true) 3145 } 3146 3147 func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) { 3148 testTransportReuseConnection_Gzip(t, false) 3149 } 3150 3151 // Make sure we re-use underlying TCP connection for gzipped responses too. 3152 func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) { 3153 defer afterTest(t) 3154 addr := make(chan string, 2) 3155 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3156 addr <- r.RemoteAddr 3157 w.Header().Set("Content-Encoding", "gzip") 3158 if chunked { 3159 w.(Flusher).Flush() 3160 } 3161 w.Write(rgz) // arbitrary gzip response 3162 })) 3163 defer ts.Close() 3164 3165 tr := &Transport{} 3166 defer tr.CloseIdleConnections() 3167 c := &Client{Transport: tr} 3168 for i := 0; i < 2; i++ { 3169 res, err := c.Get(ts.URL) 3170 if err != nil { 3171 t.Fatal(err) 3172 } 3173 buf := make([]byte, len(rgz)) 3174 if n, err := io.ReadFull(res.Body, buf); err != nil { 3175 t.Errorf("%d. ReadFull = %v, %v", i, n, err) 3176 } 3177 // Note: no res.Body.Close call. It should work without it, 3178 // since the flate.Reader's internal buffering will hit EOF 3179 // and that should be sufficient. 3180 } 3181 a1, a2 := <-addr, <-addr 3182 if a1 != a2 { 3183 t.Fatalf("didn't reuse connection") 3184 } 3185 } 3186 3187 func TestTransportResponseHeaderLength(t *testing.T) { 3188 defer afterTest(t) 3189 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3190 if r.URL.Path == "/long" { 3191 w.Header().Set("Long", strings.Repeat("a", 1<<20)) 3192 } 3193 })) 3194 defer ts.Close() 3195 3196 tr := &Transport{ 3197 MaxResponseHeaderBytes: 512 << 10, 3198 } 3199 defer tr.CloseIdleConnections() 3200 c := &Client{Transport: tr} 3201 if res, err := c.Get(ts.URL); err != nil { 3202 t.Fatal(err) 3203 } else { 3204 res.Body.Close() 3205 } 3206 3207 res, err := c.Get(ts.URL + "/long") 3208 if err == nil { 3209 defer res.Body.Close() 3210 var n int64 3211 for k, vv := range res.Header { 3212 for _, v := range vv { 3213 n += int64(len(k)) + int64(len(v)) 3214 } 3215 } 3216 t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n) 3217 } 3218 if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) { 3219 t.Errorf("got error: %v; want %q", err, want) 3220 } 3221 } 3222 3223 func TestTransportEventTrace(t *testing.T) { testTransportEventTrace(t, h1Mode, false) } 3224 func TestTransportEventTrace_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, false) } 3225 3226 // test a non-nil httptrace.ClientTrace but with all hooks set to zero. 3227 func TestTransportEventTrace_NoHooks(t *testing.T) { testTransportEventTrace(t, h1Mode, true) } 3228 func TestTransportEventTrace_NoHooks_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, true) } 3229 3230 func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { 3231 defer afterTest(t) 3232 const resBody = "some body" 3233 gotWroteReqEvent := make(chan struct{}) 3234 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3235 if _, err := ioutil.ReadAll(r.Body); err != nil { 3236 t.Error(err) 3237 } 3238 if !noHooks { 3239 select { 3240 case <-gotWroteReqEvent: 3241 case <-time.After(5 * time.Second): 3242 t.Error("timeout waiting for WroteRequest event") 3243 } 3244 } 3245 io.WriteString(w, resBody) 3246 })) 3247 defer cst.close() 3248 3249 cst.tr.ExpectContinueTimeout = 1 * time.Second 3250 3251 var mu sync.Mutex 3252 var buf bytes.Buffer 3253 logf := func(format string, args ...interface{}) { 3254 mu.Lock() 3255 defer mu.Unlock() 3256 fmt.Fprintf(&buf, format, args...) 3257 buf.WriteByte('\n') 3258 } 3259 3260 addrStr := cst.ts.Listener.Addr().String() 3261 ip, port, err := net.SplitHostPort(addrStr) 3262 if err != nil { 3263 t.Fatal(err) 3264 } 3265 3266 // Install a fake DNS server. 3267 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3268 if host != "dns-is-faked.golang" { 3269 t.Errorf("unexpected DNS host lookup for %q", host) 3270 return nil, nil 3271 } 3272 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3273 }) 3274 3275 req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader("some body")) 3276 trace := &httptrace.ClientTrace{ 3277 GetConn: func(hostPort string) { logf("Getting conn for %v ...", hostPort) }, 3278 GotConn: func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) }, 3279 GotFirstResponseByte: func() { logf("first response byte") }, 3280 PutIdleConn: func(err error) { logf("PutIdleConn = %v", err) }, 3281 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) }, 3282 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) }, 3283 ConnectStart: func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) }, 3284 ConnectDone: func(network, addr string, err error) { 3285 if err != nil { 3286 t.Errorf("ConnectDone: %v", err) 3287 } 3288 logf("ConnectDone: connected to %s %s = %v", network, addr, err) 3289 }, 3290 Wait100Continue: func() { logf("Wait100Continue") }, 3291 Got100Continue: func() { logf("Got100Continue") }, 3292 WroteRequest: func(e httptrace.WroteRequestInfo) { 3293 close(gotWroteReqEvent) 3294 logf("WroteRequest: %+v", e) 3295 }, 3296 } 3297 if noHooks { 3298 // zero out all func pointers, trying to get some path to crash 3299 *trace = httptrace.ClientTrace{} 3300 } 3301 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 3302 3303 req.Header.Set("Expect", "100-continue") 3304 res, err := cst.c.Do(req) 3305 if err != nil { 3306 t.Fatal(err) 3307 } 3308 logf("got roundtrip.response") 3309 slurp, err := ioutil.ReadAll(res.Body) 3310 if err != nil { 3311 t.Fatal(err) 3312 } 3313 logf("consumed body") 3314 if string(slurp) != resBody || res.StatusCode != 200 { 3315 t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody) 3316 } 3317 res.Body.Close() 3318 3319 if noHooks { 3320 // Done at this point. Just testing a full HTTP 3321 // requests can happen with a trace pointing to a zero 3322 // ClientTrace, full of nil func pointers. 3323 return 3324 } 3325 3326 got := buf.String() 3327 wantOnce := func(sub string) { 3328 if strings.Count(got, sub) != 1 { 3329 t.Errorf("expected substring %q exactly once in output.", sub) 3330 } 3331 } 3332 wantOnceOrMore := func(sub string) { 3333 if strings.Count(got, sub) == 0 { 3334 t.Errorf("expected substring %q at least once in output.", sub) 3335 } 3336 } 3337 wantOnce("Getting conn for dns-is-faked.golang:" + port) 3338 wantOnce("DNS start: {Host:dns-is-faked.golang}") 3339 wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}") 3340 wantOnce("got conn: {") 3341 wantOnceOrMore("Connecting to tcp " + addrStr) 3342 wantOnceOrMore("connected to tcp " + addrStr + " = <nil>") 3343 wantOnce("Reused:false WasIdle:false IdleTime:0s") 3344 wantOnce("first response byte") 3345 if !h2 { 3346 wantOnce("PutIdleConn = <nil>") 3347 } 3348 wantOnce("Wait100Continue") 3349 wantOnce("Got100Continue") 3350 wantOnce("WroteRequest: {Err:<nil>}") 3351 if strings.Contains(got, " to udp ") { 3352 t.Errorf("should not see UDP (DNS) connections") 3353 } 3354 if t.Failed() { 3355 t.Errorf("Output:\n%s", got) 3356 } 3357 } 3358 3359 func TestTransportEventTraceRealDNS(t *testing.T) { 3360 defer afterTest(t) 3361 tr := &Transport{} 3362 defer tr.CloseIdleConnections() 3363 c := &Client{Transport: tr} 3364 3365 var mu sync.Mutex 3366 var buf bytes.Buffer 3367 logf := func(format string, args ...interface{}) { 3368 mu.Lock() 3369 defer mu.Unlock() 3370 fmt.Fprintf(&buf, format, args...) 3371 buf.WriteByte('\n') 3372 } 3373 3374 req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil) 3375 trace := &httptrace.ClientTrace{ 3376 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) }, 3377 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) }, 3378 ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) }, 3379 ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) }, 3380 } 3381 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 3382 3383 resp, err := c.Do(req) 3384 if err == nil { 3385 resp.Body.Close() 3386 t.Fatal("expected error during DNS lookup") 3387 } 3388 3389 got := buf.String() 3390 wantSub := func(sub string) { 3391 if !strings.Contains(got, sub) { 3392 t.Errorf("expected substring %q in output.", sub) 3393 } 3394 } 3395 wantSub("DNSStart: {Host:dns-should-not-resolve.golang}") 3396 wantSub("DNSDone: {Addrs:[] Err:") 3397 if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") { 3398 t.Errorf("should not see Connect events") 3399 } 3400 if t.Failed() { 3401 t.Errorf("Output:\n%s", got) 3402 } 3403 } 3404 3405 func TestTransportMaxIdleConns(t *testing.T) { 3406 defer afterTest(t) 3407 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3408 // No body for convenience. 3409 })) 3410 defer ts.Close() 3411 tr := &Transport{ 3412 MaxIdleConns: 4, 3413 } 3414 defer tr.CloseIdleConnections() 3415 3416 ip, port, err := net.SplitHostPort(ts.Listener.Addr().String()) 3417 if err != nil { 3418 t.Fatal(err) 3419 } 3420 c := &Client{Transport: tr} 3421 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3422 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3423 }) 3424 3425 hitHost := func(n int) { 3426 req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil) 3427 req = req.WithContext(ctx) 3428 res, err := c.Do(req) 3429 if err != nil { 3430 t.Fatal(err) 3431 } 3432 res.Body.Close() 3433 } 3434 for i := 0; i < 4; i++ { 3435 hitHost(i) 3436 } 3437 want := []string{ 3438 "|http|host-0.dns-is-faked.golang:" + port, 3439 "|http|host-1.dns-is-faked.golang:" + port, 3440 "|http|host-2.dns-is-faked.golang:" + port, 3441 "|http|host-3.dns-is-faked.golang:" + port, 3442 } 3443 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3444 t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want) 3445 } 3446 3447 // Now hitting the 5th host should kick out the first host: 3448 hitHost(4) 3449 want = []string{ 3450 "|http|host-1.dns-is-faked.golang:" + port, 3451 "|http|host-2.dns-is-faked.golang:" + port, 3452 "|http|host-3.dns-is-faked.golang:" + port, 3453 "|http|host-4.dns-is-faked.golang:" + port, 3454 } 3455 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3456 t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want) 3457 } 3458 } 3459 3460 func TestTransportIdleConnTimeout(t *testing.T) { 3461 if testing.Short() { 3462 t.Skip("skipping in short mode") 3463 } 3464 defer afterTest(t) 3465 3466 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3467 // No body for convenience. 3468 })) 3469 defer ts.Close() 3470 3471 const timeout = 1 * time.Second 3472 tr := &Transport{ 3473 IdleConnTimeout: timeout, 3474 } 3475 defer tr.CloseIdleConnections() 3476 c := &Client{Transport: tr} 3477 3478 var conn string 3479 doReq := func(n int) { 3480 req, _ := NewRequest("GET", ts.URL, nil) 3481 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 3482 PutIdleConn: func(err error) { 3483 if err != nil { 3484 t.Errorf("failed to keep idle conn: %v", err) 3485 } 3486 }, 3487 })) 3488 res, err := c.Do(req) 3489 if err != nil { 3490 t.Fatal(err) 3491 } 3492 res.Body.Close() 3493 conns := tr.IdleConnStrsForTesting() 3494 if len(conns) != 1 { 3495 t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns) 3496 } 3497 if conn == "" { 3498 conn = conns[0] 3499 } 3500 if conn != conns[0] { 3501 t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n) 3502 } 3503 } 3504 for i := 0; i < 3; i++ { 3505 doReq(i) 3506 time.Sleep(timeout / 2) 3507 } 3508 time.Sleep(timeout * 3 / 2) 3509 if got := tr.IdleConnStrsForTesting(); len(got) != 0 { 3510 t.Errorf("idle conns = %q; want none", got) 3511 } 3512 } 3513 3514 // Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an 3515 // HTTP/2 connection was established but but its caller no longer 3516 // wanted it. (Assuming the connection cache was enabled, which it is 3517 // by default) 3518 // 3519 // This test reproduced the crash by setting the IdleConnTimeout low 3520 // (to make the test reasonable) and then making a request which is 3521 // canceled by the DialTLS hook, which then also waits to return the 3522 // real connection until after the RoundTrip saw the error. Then we 3523 // know the successful tls.Dial from DialTLS will need to go into the 3524 // idle pool. Then we give it a of time to explode. 3525 func TestIdleConnH2Crash(t *testing.T) { 3526 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3527 // nothing 3528 })) 3529 defer cst.close() 3530 3531 ctx, cancel := context.WithCancel(context.Background()) 3532 defer cancel() 3533 3534 gotErr := make(chan bool, 1) 3535 3536 cst.tr.IdleConnTimeout = 5 * time.Millisecond 3537 cst.tr.DialTLS = func(network, addr string) (net.Conn, error) { 3538 cancel() 3539 <-gotErr 3540 c, err := tls.Dial(network, addr, &tls.Config{ 3541 InsecureSkipVerify: true, 3542 NextProtos: []string{"h2"}, 3543 }) 3544 if err != nil { 3545 t.Error(err) 3546 return nil, err 3547 } 3548 if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" { 3549 t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2") 3550 c.Close() 3551 return nil, errors.New("bogus") 3552 } 3553 return c, nil 3554 } 3555 3556 req, _ := NewRequest("GET", cst.ts.URL, nil) 3557 req = req.WithContext(ctx) 3558 res, err := cst.c.Do(req) 3559 if err == nil { 3560 res.Body.Close() 3561 t.Fatal("unexpected success") 3562 } 3563 gotErr <- true 3564 3565 // Wait for the explosion. 3566 time.Sleep(cst.tr.IdleConnTimeout * 10) 3567 } 3568 3569 type funcConn struct { 3570 net.Conn 3571 read func([]byte) (int, error) 3572 write func([]byte) (int, error) 3573 } 3574 3575 func (c funcConn) Read(p []byte) (int, error) { return c.read(p) } 3576 func (c funcConn) Write(p []byte) (int, error) { return c.write(p) } 3577 func (c funcConn) Close() error { return nil } 3578 3579 // Issue 16465: Transport.RoundTrip should return the raw net.Conn.Read error from Peek 3580 // back to the caller. 3581 func TestTransportReturnsPeekError(t *testing.T) { 3582 errValue := errors.New("specific error value") 3583 3584 wrote := make(chan struct{}) 3585 var wroteOnce sync.Once 3586 3587 tr := &Transport{ 3588 Dial: func(network, addr string) (net.Conn, error) { 3589 c := funcConn{ 3590 read: func([]byte) (int, error) { 3591 <-wrote 3592 return 0, errValue 3593 }, 3594 write: func(p []byte) (int, error) { 3595 wroteOnce.Do(func() { close(wrote) }) 3596 return len(p), nil 3597 }, 3598 } 3599 return c, nil 3600 }, 3601 } 3602 _, err := tr.RoundTrip(httptest.NewRequest("GET", "http://fake.tld/", nil)) 3603 if err != errValue { 3604 t.Errorf("error = %#v; want %v", err, errValue) 3605 } 3606 } 3607 3608 var errFakeRoundTrip = errors.New("fake roundtrip") 3609 3610 type funcRoundTripper func() 3611 3612 func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) { 3613 fn() 3614 return nil, errFakeRoundTrip 3615 } 3616 3617 func wantBody(res *Response, err error, want string) error { 3618 if err != nil { 3619 return err 3620 } 3621 slurp, err := ioutil.ReadAll(res.Body) 3622 if err != nil { 3623 return fmt.Errorf("error reading body: %v", err) 3624 } 3625 if string(slurp) != want { 3626 return fmt.Errorf("body = %q; want %q", slurp, want) 3627 } 3628 if err := res.Body.Close(); err != nil { 3629 return fmt.Errorf("body Close = %v", err) 3630 } 3631 return nil 3632 } 3633 3634 func newLocalListener(t *testing.T) net.Listener { 3635 ln, err := net.Listen("tcp", "127.0.0.1:0") 3636 if err != nil { 3637 ln, err = net.Listen("tcp6", "[::1]:0") 3638 } 3639 if err != nil { 3640 t.Fatal(err) 3641 } 3642 return ln 3643 } 3644 3645 type countCloseReader struct { 3646 n *int 3647 io.Reader 3648 } 3649 3650 func (cr countCloseReader) Close() error { 3651 (*cr.n)++ 3652 return nil 3653 } 3654 3655 // rgz is a gzip quine that uncompresses to itself. 3656 var rgz = []byte{ 3657 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 3658 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 3659 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 3660 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 3661 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 3662 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 3663 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 3664 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 3665 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 3666 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 3667 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 3668 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 3669 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 3670 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 3671 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 3672 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 3673 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 3674 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 3675 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 3676 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 3677 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 3678 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 3679 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 3680 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 3681 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 3682 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 3683 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 3684 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 3685 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 3686 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 3687 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 3688 0x00, 0x00, 3689 }