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