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