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