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