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