github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/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" 23 "net/http/httptest" 24 "net/url" 25 "os" 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.(http.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 := http.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 http://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 509 // Do a bunch of traffic from different goroutines. Send to activityc 510 // after each request completes, regardless of whether it failed. 511 const ( 512 numClients = 50 513 reqsPerClient = 250 514 ) 515 activityc := make(chan bool) 516 for i := 0; i < numClients; i++ { 517 go func() { 518 for i := 0; i < reqsPerClient; i++ { 519 res, err := c.Get(ts.URL) 520 if err == nil { 521 // We expect errors since the server is 522 // hanging up on us after telling us to 523 // send more requests, so we don't 524 // actually care what the error is. 525 // But we want to close the body in cases 526 // where we won the race. 527 res.Body.Close() 528 } 529 activityc <- true 530 } 531 }() 532 } 533 534 // Make sure all the request come back, one way or another. 535 for i := 0; i < numClients*reqsPerClient; i++ { 536 select { 537 case <-activityc: 538 case <-time.After(5 * time.Second): 539 t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile") 540 } 541 } 542 } 543 544 // TestTransportHeadResponses verifies that we deal with Content-Lengths 545 // with no bodies properly 546 func TestTransportHeadResponses(t *testing.T) { 547 defer afterTest(t) 548 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 549 if r.Method != "HEAD" { 550 panic("expected HEAD; got " + r.Method) 551 } 552 w.Header().Set("Content-Length", "123") 553 w.WriteHeader(200) 554 })) 555 defer ts.Close() 556 557 tr := &Transport{DisableKeepAlives: false} 558 c := &Client{Transport: tr} 559 for i := 0; i < 2; i++ { 560 res, err := c.Head(ts.URL) 561 if err != nil { 562 t.Errorf("error on loop %d: %v", i, err) 563 continue 564 } 565 if e, g := "123", res.Header.Get("Content-Length"); e != g { 566 t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g) 567 } 568 if e, g := int64(123), res.ContentLength; e != g { 569 t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g) 570 } 571 if all, err := ioutil.ReadAll(res.Body); err != nil { 572 t.Errorf("loop %d: Body ReadAll: %v", i, err) 573 } else if len(all) != 0 { 574 t.Errorf("Bogus body %q", all) 575 } 576 } 577 } 578 579 // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding 580 // on responses to HEAD requests. 581 func TestTransportHeadChunkedResponse(t *testing.T) { 582 defer afterTest(t) 583 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 584 if r.Method != "HEAD" { 585 panic("expected HEAD; got " + r.Method) 586 } 587 w.Header().Set("Transfer-Encoding", "chunked") // client should ignore 588 w.Header().Set("x-client-ipport", r.RemoteAddr) 589 w.WriteHeader(200) 590 })) 591 defer ts.Close() 592 593 tr := &Transport{DisableKeepAlives: false} 594 c := &Client{Transport: tr} 595 596 res1, err := c.Head(ts.URL) 597 if err != nil { 598 t.Fatalf("request 1 error: %v", err) 599 } 600 res2, err := c.Head(ts.URL) 601 if err != nil { 602 t.Fatalf("request 2 error: %v", err) 603 } 604 if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 { 605 t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2) 606 } 607 } 608 609 var roundTripTests = []struct { 610 accept string 611 expectAccept string 612 compressed bool 613 }{ 614 // Requests with no accept-encoding header use transparent compression 615 {"", "gzip", false}, 616 // Requests with other accept-encoding should pass through unmodified 617 {"foo", "foo", false}, 618 // Requests with accept-encoding == gzip should be passed through 619 {"gzip", "gzip", true}, 620 } 621 622 // Test that the modification made to the Request by the RoundTripper is cleaned up 623 func TestRoundTripGzip(t *testing.T) { 624 defer afterTest(t) 625 const responseBody = "test response body" 626 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 627 accept := req.Header.Get("Accept-Encoding") 628 if expect := req.FormValue("expect_accept"); accept != expect { 629 t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q", 630 req.FormValue("testnum"), accept, expect) 631 } 632 if accept == "gzip" { 633 rw.Header().Set("Content-Encoding", "gzip") 634 gz := gzip.NewWriter(rw) 635 gz.Write([]byte(responseBody)) 636 gz.Close() 637 } else { 638 rw.Header().Set("Content-Encoding", accept) 639 rw.Write([]byte(responseBody)) 640 } 641 })) 642 defer ts.Close() 643 644 for i, test := range roundTripTests { 645 // Test basic request (no accept-encoding) 646 req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil) 647 if test.accept != "" { 648 req.Header.Set("Accept-Encoding", test.accept) 649 } 650 res, err := DefaultTransport.RoundTrip(req) 651 var body []byte 652 if test.compressed { 653 var r *gzip.Reader 654 r, err = gzip.NewReader(res.Body) 655 if err != nil { 656 t.Errorf("%d. gzip NewReader: %v", i, err) 657 continue 658 } 659 body, err = ioutil.ReadAll(r) 660 res.Body.Close() 661 } else { 662 body, err = ioutil.ReadAll(res.Body) 663 } 664 if err != nil { 665 t.Errorf("%d. Error: %q", i, err) 666 continue 667 } 668 if g, e := string(body), responseBody; g != e { 669 t.Errorf("%d. body = %q; want %q", i, g, e) 670 } 671 if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e { 672 t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e) 673 } 674 if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e { 675 t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e) 676 } 677 } 678 679 } 680 681 func TestTransportGzip(t *testing.T) { 682 defer afterTest(t) 683 const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 684 const nRandBytes = 1024 * 1024 685 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 686 if req.Method == "HEAD" { 687 if g := req.Header.Get("Accept-Encoding"); g != "" { 688 t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g) 689 } 690 return 691 } 692 if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e { 693 t.Errorf("Accept-Encoding = %q, want %q", g, e) 694 } 695 rw.Header().Set("Content-Encoding", "gzip") 696 697 var w io.Writer = rw 698 var buf bytes.Buffer 699 if req.FormValue("chunked") == "0" { 700 w = &buf 701 defer io.Copy(rw, &buf) 702 defer func() { 703 rw.Header().Set("Content-Length", strconv.Itoa(buf.Len())) 704 }() 705 } 706 gz := gzip.NewWriter(w) 707 gz.Write([]byte(testString)) 708 if req.FormValue("body") == "large" { 709 io.CopyN(gz, rand.Reader, nRandBytes) 710 } 711 gz.Close() 712 })) 713 defer ts.Close() 714 715 for _, chunked := range []string{"1", "0"} { 716 c := &Client{Transport: &Transport{}} 717 718 // First fetch something large, but only read some of it. 719 res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked) 720 if err != nil { 721 t.Fatalf("large get: %v", err) 722 } 723 buf := make([]byte, len(testString)) 724 n, err := io.ReadFull(res.Body, buf) 725 if err != nil { 726 t.Fatalf("partial read of large response: size=%d, %v", n, err) 727 } 728 if e, g := testString, string(buf); e != g { 729 t.Errorf("partial read got %q, expected %q", g, e) 730 } 731 res.Body.Close() 732 // Read on the body, even though it's closed 733 n, err = res.Body.Read(buf) 734 if n != 0 || err == nil { 735 t.Errorf("expected error post-closed large Read; got = %d, %v", n, err) 736 } 737 738 // Then something small. 739 res, err = c.Get(ts.URL + "/?chunked=" + chunked) 740 if err != nil { 741 t.Fatal(err) 742 } 743 body, err := ioutil.ReadAll(res.Body) 744 if err != nil { 745 t.Fatal(err) 746 } 747 if g, e := string(body), testString; g != e { 748 t.Fatalf("body = %q; want %q", g, e) 749 } 750 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 751 t.Fatalf("Content-Encoding = %q; want %q", g, e) 752 } 753 754 // Read on the body after it's been fully read: 755 n, err = res.Body.Read(buf) 756 if n != 0 || err == nil { 757 t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err) 758 } 759 res.Body.Close() 760 n, err = res.Body.Read(buf) 761 if n != 0 || err == nil { 762 t.Errorf("expected Read error after Close; got %d, %v", n, err) 763 } 764 } 765 766 // And a HEAD request too, because they're always weird. 767 c := &Client{Transport: &Transport{}} 768 res, err := c.Head(ts.URL) 769 if err != nil { 770 t.Fatalf("Head: %v", err) 771 } 772 if res.StatusCode != 200 { 773 t.Errorf("Head status=%d; want=200", res.StatusCode) 774 } 775 } 776 777 func TestTransportProxy(t *testing.T) { 778 defer afterTest(t) 779 ch := make(chan string, 1) 780 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 781 ch <- "real server" 782 })) 783 defer ts.Close() 784 proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 785 ch <- "proxy for " + r.URL.String() 786 })) 787 defer proxy.Close() 788 789 pu, err := url.Parse(proxy.URL) 790 if err != nil { 791 t.Fatal(err) 792 } 793 c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}} 794 c.Head(ts.URL) 795 got := <-ch 796 want := "proxy for " + ts.URL + "/" 797 if got != want { 798 t.Errorf("want %q, got %q", want, got) 799 } 800 } 801 802 // TestTransportGzipRecursive sends a gzip quine and checks that the 803 // client gets the same value back. This is more cute than anything, 804 // but checks that we don't recurse forever, and checks that 805 // Content-Encoding is removed. 806 func TestTransportGzipRecursive(t *testing.T) { 807 defer afterTest(t) 808 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 809 w.Header().Set("Content-Encoding", "gzip") 810 w.Write(rgz) 811 })) 812 defer ts.Close() 813 814 c := &Client{Transport: &Transport{}} 815 res, err := c.Get(ts.URL) 816 if err != nil { 817 t.Fatal(err) 818 } 819 body, err := ioutil.ReadAll(res.Body) 820 if err != nil { 821 t.Fatal(err) 822 } 823 if !bytes.Equal(body, rgz) { 824 t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x", 825 body, rgz) 826 } 827 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 828 t.Fatalf("Content-Encoding = %q; want %q", g, e) 829 } 830 } 831 832 // golang.org/issue/7750: request fails when server replies with 833 // a short gzip body 834 func TestTransportGzipShort(t *testing.T) { 835 defer afterTest(t) 836 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 837 w.Header().Set("Content-Encoding", "gzip") 838 w.Write([]byte{0x1f, 0x8b}) 839 })) 840 defer ts.Close() 841 842 tr := &Transport{} 843 defer tr.CloseIdleConnections() 844 c := &Client{Transport: tr} 845 res, err := c.Get(ts.URL) 846 if err != nil { 847 t.Fatal(err) 848 } 849 defer res.Body.Close() 850 _, err = ioutil.ReadAll(res.Body) 851 if err == nil { 852 t.Fatal("Expect an error from reading a body.") 853 } 854 if err != io.ErrUnexpectedEOF { 855 t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err) 856 } 857 } 858 859 // tests that persistent goroutine connections shut down when no longer desired. 860 func TestTransportPersistConnLeak(t *testing.T) { 861 if runtime.GOOS == "plan9" { 862 t.Skip("skipping test; see http://golang.org/issue/7237") 863 } 864 defer afterTest(t) 865 gotReqCh := make(chan bool) 866 unblockCh := make(chan bool) 867 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 868 gotReqCh <- true 869 <-unblockCh 870 w.Header().Set("Content-Length", "0") 871 w.WriteHeader(204) 872 })) 873 defer ts.Close() 874 875 tr := &Transport{} 876 c := &Client{Transport: tr} 877 878 n0 := runtime.NumGoroutine() 879 880 const numReq = 25 881 didReqCh := make(chan bool) 882 for i := 0; i < numReq; i++ { 883 go func() { 884 res, err := c.Get(ts.URL) 885 didReqCh <- true 886 if err != nil { 887 t.Errorf("client fetch error: %v", err) 888 return 889 } 890 res.Body.Close() 891 }() 892 } 893 894 // Wait for all goroutines to be stuck in the Handler. 895 for i := 0; i < numReq; i++ { 896 <-gotReqCh 897 } 898 899 nhigh := runtime.NumGoroutine() 900 901 // Tell all handlers to unblock and reply. 902 for i := 0; i < numReq; i++ { 903 unblockCh <- true 904 } 905 906 // Wait for all HTTP clients to be done. 907 for i := 0; i < numReq; i++ { 908 <-didReqCh 909 } 910 911 tr.CloseIdleConnections() 912 time.Sleep(100 * time.Millisecond) 913 runtime.GC() 914 runtime.GC() // even more. 915 nfinal := runtime.NumGoroutine() 916 917 growth := nfinal - n0 918 919 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 920 // Previously we were leaking one per numReq. 921 if int(growth) > 5 { 922 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 923 t.Error("too many new goroutines") 924 } 925 } 926 927 // golang.org/issue/4531: Transport leaks goroutines when 928 // request.ContentLength is explicitly short 929 func TestTransportPersistConnLeakShortBody(t *testing.T) { 930 if runtime.GOOS == "plan9" { 931 t.Skip("skipping test; see http://golang.org/issue/7237") 932 } 933 defer afterTest(t) 934 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 935 })) 936 defer ts.Close() 937 938 tr := &Transport{} 939 c := &Client{Transport: tr} 940 941 n0 := runtime.NumGoroutine() 942 body := []byte("Hello") 943 for i := 0; i < 20; i++ { 944 req, err := NewRequest("POST", ts.URL, bytes.NewReader(body)) 945 if err != nil { 946 t.Fatal(err) 947 } 948 req.ContentLength = int64(len(body) - 2) // explicitly short 949 _, err = c.Do(req) 950 if err == nil { 951 t.Fatal("Expect an error from writing too long of a body.") 952 } 953 } 954 nhigh := runtime.NumGoroutine() 955 tr.CloseIdleConnections() 956 time.Sleep(400 * time.Millisecond) 957 runtime.GC() 958 nfinal := runtime.NumGoroutine() 959 960 growth := nfinal - n0 961 962 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 963 // Previously we were leaking one per numReq. 964 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 965 if int(growth) > 5 { 966 t.Error("too many new goroutines") 967 } 968 } 969 970 // This used to crash; http://golang.org/issue/3266 971 func TestTransportIdleConnCrash(t *testing.T) { 972 defer afterTest(t) 973 tr := &Transport{} 974 c := &Client{Transport: tr} 975 976 unblockCh := make(chan bool, 1) 977 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 978 <-unblockCh 979 tr.CloseIdleConnections() 980 })) 981 defer ts.Close() 982 983 didreq := make(chan bool) 984 go func() { 985 res, err := c.Get(ts.URL) 986 if err != nil { 987 t.Error(err) 988 } else { 989 res.Body.Close() // returns idle conn 990 } 991 didreq <- true 992 }() 993 unblockCh <- true 994 <-didreq 995 } 996 997 // Test that the transport doesn't close the TCP connection early, 998 // before the response body has been read. This was a regression 999 // which sadly lacked a triggering test. The large response body made 1000 // the old race easier to trigger. 1001 func TestIssue3644(t *testing.T) { 1002 defer afterTest(t) 1003 const numFoos = 5000 1004 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1005 w.Header().Set("Connection", "close") 1006 for i := 0; i < numFoos; i++ { 1007 w.Write([]byte("foo ")) 1008 } 1009 })) 1010 defer ts.Close() 1011 tr := &Transport{} 1012 c := &Client{Transport: tr} 1013 res, err := c.Get(ts.URL) 1014 if err != nil { 1015 t.Fatal(err) 1016 } 1017 defer res.Body.Close() 1018 bs, err := ioutil.ReadAll(res.Body) 1019 if err != nil { 1020 t.Fatal(err) 1021 } 1022 if len(bs) != numFoos*len("foo ") { 1023 t.Errorf("unexpected response length") 1024 } 1025 } 1026 1027 // Test that a client receives a server's reply, even if the server doesn't read 1028 // the entire request body. 1029 func TestIssue3595(t *testing.T) { 1030 defer afterTest(t) 1031 const deniedMsg = "sorry, denied." 1032 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1033 Error(w, deniedMsg, StatusUnauthorized) 1034 })) 1035 defer ts.Close() 1036 tr := &Transport{} 1037 c := &Client{Transport: tr} 1038 res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a')) 1039 if err != nil { 1040 t.Errorf("Post: %v", err) 1041 return 1042 } 1043 got, err := ioutil.ReadAll(res.Body) 1044 if err != nil { 1045 t.Fatalf("Body ReadAll: %v", err) 1046 } 1047 if !strings.Contains(string(got), deniedMsg) { 1048 t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg) 1049 } 1050 } 1051 1052 // From http://golang.org/issue/4454 , 1053 // "client fails to handle requests with no body and chunked encoding" 1054 func TestChunkedNoContent(t *testing.T) { 1055 defer afterTest(t) 1056 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1057 w.WriteHeader(StatusNoContent) 1058 })) 1059 defer ts.Close() 1060 1061 for _, closeBody := range []bool{true, false} { 1062 c := &Client{Transport: &Transport{}} 1063 const n = 4 1064 for i := 1; i <= n; i++ { 1065 res, err := c.Get(ts.URL) 1066 if err != nil { 1067 t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err) 1068 } else { 1069 if closeBody { 1070 res.Body.Close() 1071 } 1072 } 1073 } 1074 } 1075 } 1076 1077 func TestTransportConcurrency(t *testing.T) { 1078 defer afterTest(t) 1079 maxProcs, numReqs := 16, 500 1080 if testing.Short() { 1081 maxProcs, numReqs = 4, 50 1082 } 1083 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1084 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1085 fmt.Fprintf(w, "%v", r.FormValue("echo")) 1086 })) 1087 defer ts.Close() 1088 1089 var wg sync.WaitGroup 1090 wg.Add(numReqs) 1091 1092 // Due to the Transport's "socket late binding" (see 1093 // idleConnCh in transport.go), the numReqs HTTP requests 1094 // below can finish with a dial still outstanding. To keep 1095 // the leak checker happy, keep track of pending dials and 1096 // wait for them to finish (and be closed or returned to the 1097 // idle pool) before we close idle connections. 1098 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done) 1099 defer SetPendingDialHooks(nil, nil) 1100 1101 tr := &Transport{} 1102 defer tr.CloseIdleConnections() 1103 1104 c := &Client{Transport: tr} 1105 reqs := make(chan string) 1106 defer close(reqs) 1107 1108 for i := 0; i < maxProcs*2; i++ { 1109 go func() { 1110 for req := range reqs { 1111 res, err := c.Get(ts.URL + "/?echo=" + req) 1112 if err != nil { 1113 t.Errorf("error on req %s: %v", req, err) 1114 wg.Done() 1115 continue 1116 } 1117 all, err := ioutil.ReadAll(res.Body) 1118 if err != nil { 1119 t.Errorf("read error on req %s: %v", req, err) 1120 wg.Done() 1121 continue 1122 } 1123 if string(all) != req { 1124 t.Errorf("body of req %s = %q; want %q", req, all, req) 1125 } 1126 res.Body.Close() 1127 wg.Done() 1128 } 1129 }() 1130 } 1131 for i := 0; i < numReqs; i++ { 1132 reqs <- fmt.Sprintf("request-%d", i) 1133 } 1134 wg.Wait() 1135 } 1136 1137 func TestIssue4191_InfiniteGetTimeout(t *testing.T) { 1138 if runtime.GOOS == "plan9" { 1139 t.Skip("skipping test; see http://golang.org/issue/7237") 1140 } 1141 defer afterTest(t) 1142 const debug = false 1143 mux := NewServeMux() 1144 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1145 io.Copy(w, neverEnding('a')) 1146 }) 1147 ts := httptest.NewServer(mux) 1148 timeout := 100 * time.Millisecond 1149 1150 client := &Client{ 1151 Transport: &Transport{ 1152 Dial: func(n, addr string) (net.Conn, error) { 1153 conn, err := net.Dial(n, addr) 1154 if err != nil { 1155 return nil, err 1156 } 1157 conn.SetDeadline(time.Now().Add(timeout)) 1158 if debug { 1159 conn = NewLoggingConn("client", conn) 1160 } 1161 return conn, nil 1162 }, 1163 DisableKeepAlives: true, 1164 }, 1165 } 1166 1167 getFailed := false 1168 nRuns := 5 1169 if testing.Short() { 1170 nRuns = 1 1171 } 1172 for i := 0; i < nRuns; i++ { 1173 if debug { 1174 println("run", i+1, "of", nRuns) 1175 } 1176 sres, err := client.Get(ts.URL + "/get") 1177 if err != nil { 1178 if !getFailed { 1179 // Make the timeout longer, once. 1180 getFailed = true 1181 t.Logf("increasing timeout") 1182 i-- 1183 timeout *= 10 1184 continue 1185 } 1186 t.Errorf("Error issuing GET: %v", err) 1187 break 1188 } 1189 _, err = io.Copy(ioutil.Discard, sres.Body) 1190 if err == nil { 1191 t.Errorf("Unexpected successful copy") 1192 break 1193 } 1194 } 1195 if debug { 1196 println("tests complete; waiting for handlers to finish") 1197 } 1198 ts.Close() 1199 } 1200 1201 func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) { 1202 if runtime.GOOS == "plan9" { 1203 t.Skip("skipping test; see http://golang.org/issue/7237") 1204 } 1205 defer afterTest(t) 1206 const debug = false 1207 mux := NewServeMux() 1208 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1209 io.Copy(w, neverEnding('a')) 1210 }) 1211 mux.HandleFunc("/put", func(w ResponseWriter, r *Request) { 1212 defer r.Body.Close() 1213 io.Copy(ioutil.Discard, r.Body) 1214 }) 1215 ts := httptest.NewServer(mux) 1216 timeout := 100 * time.Millisecond 1217 1218 client := &Client{ 1219 Transport: &Transport{ 1220 Dial: func(n, addr string) (net.Conn, error) { 1221 conn, err := net.Dial(n, addr) 1222 if err != nil { 1223 return nil, err 1224 } 1225 conn.SetDeadline(time.Now().Add(timeout)) 1226 if debug { 1227 conn = NewLoggingConn("client", conn) 1228 } 1229 return conn, nil 1230 }, 1231 DisableKeepAlives: true, 1232 }, 1233 } 1234 1235 getFailed := false 1236 nRuns := 5 1237 if testing.Short() { 1238 nRuns = 1 1239 } 1240 for i := 0; i < nRuns; i++ { 1241 if debug { 1242 println("run", i+1, "of", nRuns) 1243 } 1244 sres, err := client.Get(ts.URL + "/get") 1245 if err != nil { 1246 if !getFailed { 1247 // Make the timeout longer, once. 1248 getFailed = true 1249 t.Logf("increasing timeout") 1250 i-- 1251 timeout *= 10 1252 continue 1253 } 1254 t.Errorf("Error issuing GET: %v", err) 1255 break 1256 } 1257 req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body) 1258 _, err = client.Do(req) 1259 if err == nil { 1260 sres.Body.Close() 1261 t.Errorf("Unexpected successful PUT") 1262 break 1263 } 1264 sres.Body.Close() 1265 } 1266 if debug { 1267 println("tests complete; waiting for handlers to finish") 1268 } 1269 ts.Close() 1270 } 1271 1272 func TestTransportResponseHeaderTimeout(t *testing.T) { 1273 defer afterTest(t) 1274 if testing.Short() { 1275 t.Skip("skipping timeout test in -short mode") 1276 } 1277 inHandler := make(chan bool, 1) 1278 mux := NewServeMux() 1279 mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) { 1280 inHandler <- true 1281 }) 1282 mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) { 1283 inHandler <- true 1284 time.Sleep(2 * time.Second) 1285 }) 1286 ts := httptest.NewServer(mux) 1287 defer ts.Close() 1288 1289 tr := &Transport{ 1290 ResponseHeaderTimeout: 500 * time.Millisecond, 1291 } 1292 defer tr.CloseIdleConnections() 1293 c := &Client{Transport: tr} 1294 1295 tests := []struct { 1296 path string 1297 want int 1298 wantErr string 1299 }{ 1300 {path: "/fast", want: 200}, 1301 {path: "/slow", wantErr: "timeout awaiting response headers"}, 1302 {path: "/fast", want: 200}, 1303 } 1304 for i, tt := range tests { 1305 res, err := c.Get(ts.URL + tt.path) 1306 select { 1307 case <-inHandler: 1308 case <-time.After(5 * time.Second): 1309 t.Errorf("never entered handler for test index %d, %s", i, tt.path) 1310 continue 1311 } 1312 if err != nil { 1313 uerr, ok := err.(*url.Error) 1314 if !ok { 1315 t.Errorf("error is not an url.Error; got: %#v", err) 1316 continue 1317 } 1318 nerr, ok := uerr.Err.(net.Error) 1319 if !ok { 1320 t.Errorf("error does not satisfy net.Error interface; got: %#v", err) 1321 continue 1322 } 1323 if !nerr.Timeout() { 1324 t.Errorf("want timeout error; got: %q", nerr) 1325 continue 1326 } 1327 if strings.Contains(err.Error(), tt.wantErr) { 1328 continue 1329 } 1330 t.Errorf("%d. unexpected error: %v", i, err) 1331 continue 1332 } 1333 if tt.wantErr != "" { 1334 t.Errorf("%d. no error. expected error: %v", i, tt.wantErr) 1335 continue 1336 } 1337 if res.StatusCode != tt.want { 1338 t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want) 1339 } 1340 } 1341 } 1342 1343 func TestTransportCancelRequest(t *testing.T) { 1344 defer afterTest(t) 1345 if testing.Short() { 1346 t.Skip("skipping test in -short mode") 1347 } 1348 unblockc := make(chan bool) 1349 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1350 fmt.Fprintf(w, "Hello") 1351 w.(Flusher).Flush() // send headers and some body 1352 <-unblockc 1353 })) 1354 defer ts.Close() 1355 defer close(unblockc) 1356 1357 tr := &Transport{} 1358 defer tr.CloseIdleConnections() 1359 c := &Client{Transport: tr} 1360 1361 req, _ := NewRequest("GET", ts.URL, nil) 1362 res, err := c.Do(req) 1363 if err != nil { 1364 t.Fatal(err) 1365 } 1366 go func() { 1367 time.Sleep(1 * time.Second) 1368 tr.CancelRequest(req) 1369 }() 1370 t0 := time.Now() 1371 body, err := ioutil.ReadAll(res.Body) 1372 d := time.Since(t0) 1373 1374 if err == nil { 1375 t.Error("expected an error reading the body") 1376 } 1377 if string(body) != "Hello" { 1378 t.Errorf("Body = %q; want Hello", body) 1379 } 1380 if d < 500*time.Millisecond { 1381 t.Errorf("expected ~1 second delay; got %v", d) 1382 } 1383 // Verify no outstanding requests after readLoop/writeLoop 1384 // goroutines shut down. 1385 for tries := 3; tries > 0; tries-- { 1386 n := tr.NumPendingRequestsForTesting() 1387 if n == 0 { 1388 break 1389 } 1390 time.Sleep(100 * time.Millisecond) 1391 if tries == 1 { 1392 t.Errorf("pending requests = %d; want 0", n) 1393 } 1394 } 1395 } 1396 1397 func TestTransportCancelRequestInDial(t *testing.T) { 1398 defer afterTest(t) 1399 if testing.Short() { 1400 t.Skip("skipping test in -short mode") 1401 } 1402 var logbuf bytes.Buffer 1403 eventLog := log.New(&logbuf, "", 0) 1404 1405 unblockDial := make(chan bool) 1406 defer close(unblockDial) 1407 1408 inDial := make(chan bool) 1409 tr := &Transport{ 1410 Dial: func(network, addr string) (net.Conn, error) { 1411 eventLog.Println("dial: blocking") 1412 inDial <- true 1413 <-unblockDial 1414 return nil, errors.New("nope") 1415 }, 1416 } 1417 cl := &Client{Transport: tr} 1418 gotres := make(chan bool) 1419 req, _ := NewRequest("GET", "http://something.no-network.tld/", nil) 1420 go func() { 1421 _, err := cl.Do(req) 1422 eventLog.Printf("Get = %v", err) 1423 gotres <- true 1424 }() 1425 1426 select { 1427 case <-inDial: 1428 case <-time.After(5 * time.Second): 1429 t.Fatal("timeout; never saw blocking dial") 1430 } 1431 1432 eventLog.Printf("canceling") 1433 tr.CancelRequest(req) 1434 1435 select { 1436 case <-gotres: 1437 case <-time.After(5 * time.Second): 1438 panic("hang. events are: " + logbuf.String()) 1439 } 1440 1441 got := logbuf.String() 1442 want := `dial: blocking 1443 canceling 1444 Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection 1445 ` 1446 if got != want { 1447 t.Errorf("Got events:\n%s\nWant:\n%s", got, want) 1448 } 1449 } 1450 1451 // golang.org/issue/3672 -- Client can't close HTTP stream 1452 // Calling Close on a Response.Body used to just read until EOF. 1453 // Now it actually closes the TCP connection. 1454 func TestTransportCloseResponseBody(t *testing.T) { 1455 defer afterTest(t) 1456 writeErr := make(chan error, 1) 1457 msg := []byte("young\n") 1458 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1459 for { 1460 _, err := w.Write(msg) 1461 if err != nil { 1462 writeErr <- err 1463 return 1464 } 1465 w.(Flusher).Flush() 1466 } 1467 })) 1468 defer ts.Close() 1469 1470 tr := &Transport{} 1471 defer tr.CloseIdleConnections() 1472 c := &Client{Transport: tr} 1473 1474 req, _ := NewRequest("GET", ts.URL, nil) 1475 defer tr.CancelRequest(req) 1476 1477 res, err := c.Do(req) 1478 if err != nil { 1479 t.Fatal(err) 1480 } 1481 1482 const repeats = 3 1483 buf := make([]byte, len(msg)*repeats) 1484 want := bytes.Repeat(msg, repeats) 1485 1486 _, err = io.ReadFull(res.Body, buf) 1487 if err != nil { 1488 t.Fatal(err) 1489 } 1490 if !bytes.Equal(buf, want) { 1491 t.Fatalf("read %q; want %q", buf, want) 1492 } 1493 didClose := make(chan error, 1) 1494 go func() { 1495 didClose <- res.Body.Close() 1496 }() 1497 select { 1498 case err := <-didClose: 1499 if err != nil { 1500 t.Errorf("Close = %v", err) 1501 } 1502 case <-time.After(10 * time.Second): 1503 t.Fatal("too long waiting for close") 1504 } 1505 select { 1506 case err := <-writeErr: 1507 if err == nil { 1508 t.Errorf("expected non-nil write error") 1509 } 1510 case <-time.After(10 * time.Second): 1511 t.Fatal("too long waiting for write error") 1512 } 1513 } 1514 1515 type fooProto struct{} 1516 1517 func (fooProto) RoundTrip(req *Request) (*Response, error) { 1518 res := &Response{ 1519 Status: "200 OK", 1520 StatusCode: 200, 1521 Header: make(Header), 1522 Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())), 1523 } 1524 return res, nil 1525 } 1526 1527 func TestTransportAltProto(t *testing.T) { 1528 defer afterTest(t) 1529 tr := &Transport{} 1530 c := &Client{Transport: tr} 1531 tr.RegisterProtocol("foo", fooProto{}) 1532 res, err := c.Get("foo://bar.com/path") 1533 if err != nil { 1534 t.Fatal(err) 1535 } 1536 bodyb, err := ioutil.ReadAll(res.Body) 1537 if err != nil { 1538 t.Fatal(err) 1539 } 1540 body := string(bodyb) 1541 if e := "You wanted foo://bar.com/path"; body != e { 1542 t.Errorf("got response %q, want %q", body, e) 1543 } 1544 } 1545 1546 func TestTransportNoHost(t *testing.T) { 1547 defer afterTest(t) 1548 tr := &Transport{} 1549 _, err := tr.RoundTrip(&Request{ 1550 Header: make(Header), 1551 URL: &url.URL{ 1552 Scheme: "http", 1553 }, 1554 }) 1555 want := "http: no Host in request URL" 1556 if got := fmt.Sprint(err); got != want { 1557 t.Errorf("error = %v; want %q", err, want) 1558 } 1559 } 1560 1561 func TestTransportSocketLateBinding(t *testing.T) { 1562 defer afterTest(t) 1563 1564 mux := NewServeMux() 1565 fooGate := make(chan bool, 1) 1566 mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) { 1567 w.Header().Set("foo-ipport", r.RemoteAddr) 1568 w.(Flusher).Flush() 1569 <-fooGate 1570 }) 1571 mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) { 1572 w.Header().Set("bar-ipport", r.RemoteAddr) 1573 }) 1574 ts := httptest.NewServer(mux) 1575 defer ts.Close() 1576 1577 dialGate := make(chan bool, 1) 1578 tr := &Transport{ 1579 Dial: func(n, addr string) (net.Conn, error) { 1580 if <-dialGate { 1581 return net.Dial(n, addr) 1582 } 1583 return nil, errors.New("manually closed") 1584 }, 1585 DisableKeepAlives: false, 1586 } 1587 defer tr.CloseIdleConnections() 1588 c := &Client{ 1589 Transport: tr, 1590 } 1591 1592 dialGate <- true // only allow one dial 1593 fooRes, err := c.Get(ts.URL + "/foo") 1594 if err != nil { 1595 t.Fatal(err) 1596 } 1597 fooAddr := fooRes.Header.Get("foo-ipport") 1598 if fooAddr == "" { 1599 t.Fatal("No addr on /foo request") 1600 } 1601 time.AfterFunc(200*time.Millisecond, func() { 1602 // let the foo response finish so we can use its 1603 // connection for /bar 1604 fooGate <- true 1605 io.Copy(ioutil.Discard, fooRes.Body) 1606 fooRes.Body.Close() 1607 }) 1608 1609 barRes, err := c.Get(ts.URL + "/bar") 1610 if err != nil { 1611 t.Fatal(err) 1612 } 1613 barAddr := barRes.Header.Get("bar-ipport") 1614 if barAddr != fooAddr { 1615 t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr) 1616 } 1617 barRes.Body.Close() 1618 dialGate <- false 1619 } 1620 1621 // Issue 2184 1622 func TestTransportReading100Continue(t *testing.T) { 1623 defer afterTest(t) 1624 1625 const numReqs = 5 1626 reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) } 1627 reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) } 1628 1629 send100Response := func(w *io.PipeWriter, r *io.PipeReader) { 1630 defer w.Close() 1631 defer r.Close() 1632 br := bufio.NewReader(r) 1633 n := 0 1634 for { 1635 n++ 1636 req, err := ReadRequest(br) 1637 if err == io.EOF { 1638 return 1639 } 1640 if err != nil { 1641 t.Error(err) 1642 return 1643 } 1644 slurp, err := ioutil.ReadAll(req.Body) 1645 if err != nil { 1646 t.Errorf("Server request body slurp: %v", err) 1647 return 1648 } 1649 id := req.Header.Get("Request-Id") 1650 resCode := req.Header.Get("X-Want-Response-Code") 1651 if resCode == "" { 1652 resCode = "100 Continue" 1653 if string(slurp) != reqBody(n) { 1654 t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n)) 1655 } 1656 } 1657 body := fmt.Sprintf("Response number %d", n) 1658 v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s 1659 Date: Thu, 28 Feb 2013 17:55:41 GMT 1660 1661 HTTP/1.1 200 OK 1662 Content-Type: text/html 1663 Echo-Request-Id: %s 1664 Content-Length: %d 1665 1666 %s`, resCode, id, len(body), body), "\n", "\r\n", -1)) 1667 w.Write(v) 1668 if id == reqID(numReqs) { 1669 return 1670 } 1671 } 1672 1673 } 1674 1675 tr := &Transport{ 1676 Dial: func(n, addr string) (net.Conn, error) { 1677 sr, sw := io.Pipe() // server read/write 1678 cr, cw := io.Pipe() // client read/write 1679 conn := &rwTestConn{ 1680 Reader: cr, 1681 Writer: sw, 1682 closeFunc: func() error { 1683 sw.Close() 1684 cw.Close() 1685 return nil 1686 }, 1687 } 1688 go send100Response(cw, sr) 1689 return conn, nil 1690 }, 1691 DisableKeepAlives: false, 1692 } 1693 defer tr.CloseIdleConnections() 1694 c := &Client{Transport: tr} 1695 1696 testResponse := func(req *Request, name string, wantCode int) { 1697 res, err := c.Do(req) 1698 if err != nil { 1699 t.Fatalf("%s: Do: %v", name, err) 1700 } 1701 if res.StatusCode != wantCode { 1702 t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode) 1703 } 1704 if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack { 1705 t.Errorf("%s: response id %q != request id %q", name, idBack, id) 1706 } 1707 _, err = ioutil.ReadAll(res.Body) 1708 if err != nil { 1709 t.Fatalf("%s: Slurp error: %v", name, err) 1710 } 1711 } 1712 1713 // Few 100 responses, making sure we're not off-by-one. 1714 for i := 1; i <= numReqs; i++ { 1715 req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i))) 1716 req.Header.Set("Request-Id", reqID(i)) 1717 testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200) 1718 } 1719 1720 // And some other informational 1xx but non-100 responses, to test 1721 // we return them but don't re-use the connection. 1722 for i := 1; i <= numReqs; i++ { 1723 req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i))) 1724 req.Header.Set("X-Want-Response-Code", "123 Sesame Street") 1725 testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123) 1726 } 1727 } 1728 1729 type proxyFromEnvTest struct { 1730 req string // URL to fetch; blank means "http://example.com" 1731 1732 env string // HTTP_PROXY 1733 httpsenv string // HTTPS_PROXY 1734 noenv string // NO_RPXY 1735 1736 want string 1737 wanterr error 1738 } 1739 1740 func (t proxyFromEnvTest) String() string { 1741 var buf bytes.Buffer 1742 space := func() { 1743 if buf.Len() > 0 { 1744 buf.WriteByte(' ') 1745 } 1746 } 1747 if t.env != "" { 1748 fmt.Fprintf(&buf, "http_proxy=%q", t.env) 1749 } 1750 if t.httpsenv != "" { 1751 space() 1752 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv) 1753 } 1754 if t.noenv != "" { 1755 space() 1756 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv) 1757 } 1758 req := "http://example.com" 1759 if t.req != "" { 1760 req = t.req 1761 } 1762 space() 1763 fmt.Fprintf(&buf, "req=%q", req) 1764 return strings.TrimSpace(buf.String()) 1765 } 1766 1767 var proxyFromEnvTests = []proxyFromEnvTest{ 1768 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 1769 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"}, 1770 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"}, 1771 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"}, 1772 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 1773 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"}, 1774 1775 // Don't use secure for http 1776 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"}, 1777 // Use secure for https. 1778 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"}, 1779 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"}, 1780 1781 {want: "<nil>"}, 1782 1783 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 1784 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 1785 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 1786 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"}, 1787 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 1788 } 1789 1790 func TestProxyFromEnvironment(t *testing.T) { 1791 ResetProxyEnv() 1792 for _, tt := range proxyFromEnvTests { 1793 os.Setenv("HTTP_PROXY", tt.env) 1794 os.Setenv("HTTPS_PROXY", tt.httpsenv) 1795 os.Setenv("NO_PROXY", tt.noenv) 1796 ResetCachedEnvironment() 1797 reqURL := tt.req 1798 if reqURL == "" { 1799 reqURL = "http://example.com" 1800 } 1801 req, _ := NewRequest("GET", reqURL, nil) 1802 url, err := ProxyFromEnvironment(req) 1803 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 1804 t.Errorf("%v: got error = %q, want %q", tt, g, e) 1805 continue 1806 } 1807 if got := fmt.Sprintf("%s", url); got != tt.want { 1808 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 1809 } 1810 } 1811 } 1812 1813 func TestIdleConnChannelLeak(t *testing.T) { 1814 var mu sync.Mutex 1815 var n int 1816 1817 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1818 mu.Lock() 1819 n++ 1820 mu.Unlock() 1821 })) 1822 defer ts.Close() 1823 1824 tr := &Transport{ 1825 Dial: func(netw, addr string) (net.Conn, error) { 1826 return net.Dial(netw, ts.Listener.Addr().String()) 1827 }, 1828 } 1829 defer tr.CloseIdleConnections() 1830 1831 c := &Client{Transport: tr} 1832 1833 // First, without keep-alives. 1834 for _, disableKeep := range []bool{true, false} { 1835 tr.DisableKeepAlives = disableKeep 1836 for i := 0; i < 5; i++ { 1837 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i)) 1838 if err != nil { 1839 t.Fatal(err) 1840 } 1841 } 1842 if got := tr.IdleConnChMapSizeForTesting(); got != 0 { 1843 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got) 1844 } 1845 } 1846 } 1847 1848 // Verify the status quo: that the Client.Post function coerces its 1849 // body into a ReadCloser if it's a Closer, and that the Transport 1850 // then closes it. 1851 func TestTransportClosesRequestBody(t *testing.T) { 1852 defer afterTest(t) 1853 ts := httptest.NewServer(http.HandlerFunc(func(w ResponseWriter, r *Request) { 1854 io.Copy(ioutil.Discard, r.Body) 1855 })) 1856 defer ts.Close() 1857 1858 tr := &Transport{} 1859 defer tr.CloseIdleConnections() 1860 cl := &Client{Transport: tr} 1861 1862 closes := 0 1863 1864 res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")}) 1865 if err != nil { 1866 t.Fatal(err) 1867 } 1868 res.Body.Close() 1869 if closes != 1 { 1870 t.Errorf("closes = %d; want 1", closes) 1871 } 1872 } 1873 1874 func TestTransportTLSHandshakeTimeout(t *testing.T) { 1875 defer afterTest(t) 1876 if testing.Short() { 1877 t.Skip("skipping in short mode") 1878 } 1879 ln := newLocalListener(t) 1880 defer ln.Close() 1881 testdonec := make(chan struct{}) 1882 defer close(testdonec) 1883 1884 go func() { 1885 c, err := ln.Accept() 1886 if err != nil { 1887 t.Error(err) 1888 return 1889 } 1890 <-testdonec 1891 c.Close() 1892 }() 1893 1894 getdonec := make(chan struct{}) 1895 go func() { 1896 defer close(getdonec) 1897 tr := &Transport{ 1898 Dial: func(_, _ string) (net.Conn, error) { 1899 return net.Dial("tcp", ln.Addr().String()) 1900 }, 1901 TLSHandshakeTimeout: 250 * time.Millisecond, 1902 } 1903 cl := &Client{Transport: tr} 1904 _, err := cl.Get("https://dummy.tld/") 1905 if err == nil { 1906 t.Error("expected error") 1907 return 1908 } 1909 ue, ok := err.(*url.Error) 1910 if !ok { 1911 t.Errorf("expected url.Error; got %#v", err) 1912 return 1913 } 1914 ne, ok := ue.Err.(net.Error) 1915 if !ok { 1916 t.Errorf("expected net.Error; got %#v", err) 1917 return 1918 } 1919 if !ne.Timeout() { 1920 t.Errorf("expected timeout error; got %v", err) 1921 } 1922 if !strings.Contains(err.Error(), "handshake timeout") { 1923 t.Errorf("expected 'handshake timeout' in error; got %v", err) 1924 } 1925 }() 1926 select { 1927 case <-getdonec: 1928 case <-time.After(5 * time.Second): 1929 t.Error("test timeout; TLS handshake hung?") 1930 } 1931 } 1932 1933 // Trying to repro golang.org/issue/3514 1934 func TestTLSServerClosesConnection(t *testing.T) { 1935 defer afterTest(t) 1936 if runtime.GOOS == "windows" { 1937 t.Skip("skipping flaky test on Windows; golang.org/issue/7634") 1938 } 1939 closedc := make(chan bool, 1) 1940 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1941 if strings.Contains(r.URL.Path, "/keep-alive-then-die") { 1942 conn, _, _ := w.(Hijacker).Hijack() 1943 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) 1944 conn.Close() 1945 closedc <- true 1946 return 1947 } 1948 fmt.Fprintf(w, "hello") 1949 })) 1950 defer ts.Close() 1951 tr := &Transport{ 1952 TLSClientConfig: &tls.Config{ 1953 InsecureSkipVerify: true, 1954 }, 1955 } 1956 defer tr.CloseIdleConnections() 1957 client := &Client{Transport: tr} 1958 1959 var nSuccess = 0 1960 var errs []error 1961 const trials = 20 1962 for i := 0; i < trials; i++ { 1963 tr.CloseIdleConnections() 1964 res, err := client.Get(ts.URL + "/keep-alive-then-die") 1965 if err != nil { 1966 t.Fatal(err) 1967 } 1968 <-closedc 1969 slurp, err := ioutil.ReadAll(res.Body) 1970 if err != nil { 1971 t.Fatal(err) 1972 } 1973 if string(slurp) != "foo" { 1974 t.Errorf("Got %q, want foo", slurp) 1975 } 1976 1977 // Now try again and see if we successfully 1978 // pick a new connection. 1979 res, err = client.Get(ts.URL + "/") 1980 if err != nil { 1981 errs = append(errs, err) 1982 continue 1983 } 1984 slurp, err = ioutil.ReadAll(res.Body) 1985 if err != nil { 1986 errs = append(errs, err) 1987 continue 1988 } 1989 nSuccess++ 1990 } 1991 if nSuccess > 0 { 1992 t.Logf("successes = %d of %d", nSuccess, trials) 1993 } else { 1994 t.Errorf("All runs failed:") 1995 } 1996 for _, err := range errs { 1997 t.Logf(" err: %v", err) 1998 } 1999 } 2000 2001 // byteFromChanReader is an io.Reader that reads a single byte at a 2002 // time from the channel. When the channel is closed, the reader 2003 // returns io.EOF. 2004 type byteFromChanReader chan byte 2005 2006 func (c byteFromChanReader) Read(p []byte) (n int, err error) { 2007 if len(p) == 0 { 2008 return 2009 } 2010 b, ok := <-c 2011 if !ok { 2012 return 0, io.EOF 2013 } 2014 p[0] = b 2015 return 1, nil 2016 } 2017 2018 // Verifies that the Transport doesn't reuse a connection in the case 2019 // where the server replies before the request has been fully 2020 // written. We still honor that reply (see TestIssue3595), but don't 2021 // send future requests on the connection because it's then in a 2022 // questionable state. 2023 // golang.org/issue/7569 2024 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) { 2025 defer afterTest(t) 2026 var sconn struct { 2027 sync.Mutex 2028 c net.Conn 2029 } 2030 var getOkay bool 2031 closeConn := func() { 2032 sconn.Lock() 2033 defer sconn.Unlock() 2034 if sconn.c != nil { 2035 sconn.c.Close() 2036 sconn.c = nil 2037 if !getOkay { 2038 t.Logf("Closed server connection") 2039 } 2040 } 2041 } 2042 defer closeConn() 2043 2044 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2045 if r.Method == "GET" { 2046 io.WriteString(w, "bar") 2047 return 2048 } 2049 conn, _, _ := w.(Hijacker).Hijack() 2050 sconn.Lock() 2051 sconn.c = conn 2052 sconn.Unlock() 2053 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive 2054 go io.Copy(ioutil.Discard, conn) 2055 })) 2056 defer ts.Close() 2057 tr := &Transport{} 2058 defer tr.CloseIdleConnections() 2059 client := &Client{Transport: tr} 2060 2061 const bodySize = 256 << 10 2062 finalBit := make(byteFromChanReader, 1) 2063 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit)) 2064 req.ContentLength = bodySize 2065 res, err := client.Do(req) 2066 if err := wantBody(res, err, "foo"); err != nil { 2067 t.Errorf("POST response: %v", err) 2068 } 2069 donec := make(chan bool) 2070 go func() { 2071 defer close(donec) 2072 res, err = client.Get(ts.URL) 2073 if err := wantBody(res, err, "bar"); err != nil { 2074 t.Errorf("GET response: %v", err) 2075 return 2076 } 2077 getOkay = true // suppress test noise 2078 }() 2079 time.AfterFunc(5*time.Second, closeConn) 2080 select { 2081 case <-donec: 2082 finalBit <- 'x' // unblock the writeloop of the first Post 2083 close(finalBit) 2084 case <-time.After(7 * time.Second): 2085 t.Fatal("timeout waiting for GET request to finish") 2086 } 2087 } 2088 2089 type errorReader struct { 2090 err error 2091 } 2092 2093 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err } 2094 2095 type closerFunc func() error 2096 2097 func (f closerFunc) Close() error { return f() } 2098 2099 // Issue 6981 2100 func TestTransportClosesBodyOnError(t *testing.T) { 2101 if runtime.GOOS == "plan9" { 2102 t.Skip("skipping test; see http://golang.org/issue/7782") 2103 } 2104 defer afterTest(t) 2105 readBody := make(chan error, 1) 2106 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2107 _, err := ioutil.ReadAll(r.Body) 2108 readBody <- err 2109 })) 2110 defer ts.Close() 2111 fakeErr := errors.New("fake error") 2112 didClose := make(chan bool, 1) 2113 req, _ := NewRequest("POST", ts.URL, struct { 2114 io.Reader 2115 io.Closer 2116 }{ 2117 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}), 2118 closerFunc(func() error { 2119 select { 2120 case didClose <- true: 2121 default: 2122 } 2123 return nil 2124 }), 2125 }) 2126 res, err := DefaultClient.Do(req) 2127 if res != nil { 2128 defer res.Body.Close() 2129 } 2130 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 2131 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 2132 } 2133 select { 2134 case err := <-readBody: 2135 if err == nil { 2136 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 2137 } 2138 case <-time.After(5 * time.Second): 2139 t.Error("timeout waiting for server handler to complete") 2140 } 2141 select { 2142 case <-didClose: 2143 default: 2144 t.Errorf("didn't see Body.Close") 2145 } 2146 } 2147 2148 func TestTransportDialTLS(t *testing.T) { 2149 var mu sync.Mutex // guards following 2150 var gotReq, didDial bool 2151 2152 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2153 mu.Lock() 2154 gotReq = true 2155 mu.Unlock() 2156 })) 2157 defer ts.Close() 2158 tr := &Transport{ 2159 DialTLS: func(netw, addr string) (net.Conn, error) { 2160 mu.Lock() 2161 didDial = true 2162 mu.Unlock() 2163 c, err := tls.Dial(netw, addr, &tls.Config{ 2164 InsecureSkipVerify: true, 2165 }) 2166 if err != nil { 2167 return nil, err 2168 } 2169 return c, c.Handshake() 2170 }, 2171 } 2172 defer tr.CloseIdleConnections() 2173 client := &Client{Transport: tr} 2174 res, err := client.Get(ts.URL) 2175 if err != nil { 2176 t.Fatal(err) 2177 } 2178 res.Body.Close() 2179 mu.Lock() 2180 if !gotReq { 2181 t.Error("didn't get request") 2182 } 2183 if !didDial { 2184 t.Error("didn't use dial hook") 2185 } 2186 } 2187 2188 // Test for issue 8755 2189 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 2190 func TestRoundTripReturnsProxyError(t *testing.T) { 2191 badProxy := func(*http.Request) (*url.URL, error) { 2192 return nil, errors.New("errorMessage") 2193 } 2194 2195 tr := &Transport{Proxy: badProxy} 2196 2197 req, _ := http.NewRequest("GET", "http://example.com", nil) 2198 2199 _, err := tr.RoundTrip(req) 2200 2201 if err == nil { 2202 t.Error("Expected proxy error to be returned by RoundTrip") 2203 } 2204 } 2205 2206 // tests that putting an idle conn after a call to CloseIdleConns does return it 2207 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 2208 tr := &Transport{} 2209 wantIdle := func(when string, n int) bool { 2210 got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn 2211 if got == n { 2212 return true 2213 } 2214 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 2215 return false 2216 } 2217 wantIdle("start", 0) 2218 if !tr.PutIdleTestConn() { 2219 t.Fatal("put failed") 2220 } 2221 if !tr.PutIdleTestConn() { 2222 t.Fatal("second put failed") 2223 } 2224 wantIdle("after put", 2) 2225 tr.CloseIdleConnections() 2226 if !tr.IsIdleForTesting() { 2227 t.Error("should be idle after CloseIdleConnections") 2228 } 2229 wantIdle("after close idle", 0) 2230 if tr.PutIdleTestConn() { 2231 t.Fatal("put didn't fail") 2232 } 2233 wantIdle("after second put", 0) 2234 2235 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode 2236 if tr.IsIdleForTesting() { 2237 t.Error("shouldn't be idle after RequestIdleConnChForTesting") 2238 } 2239 if !tr.PutIdleTestConn() { 2240 t.Fatal("after re-activation") 2241 } 2242 wantIdle("after final put", 1) 2243 } 2244 2245 // This tests that an client requesting a content range won't also 2246 // implicitly ask for gzip support. If they want that, they need to do it 2247 // on their own. 2248 // golang.org/issue/8923 2249 func TestTransportRangeAndGzip(t *testing.T) { 2250 defer afterTest(t) 2251 reqc := make(chan *Request, 1) 2252 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2253 reqc <- r 2254 })) 2255 defer ts.Close() 2256 2257 req, _ := NewRequest("GET", ts.URL, nil) 2258 req.Header.Set("Range", "bytes=7-11") 2259 res, err := DefaultClient.Do(req) 2260 if err != nil { 2261 t.Fatal(err) 2262 } 2263 2264 select { 2265 case r := <-reqc: 2266 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 2267 t.Error("Transport advertised gzip support in the Accept header") 2268 } 2269 if r.Header.Get("Range") == "" { 2270 t.Error("no Range in request") 2271 } 2272 case <-time.After(10 * time.Second): 2273 t.Fatal("timeout") 2274 } 2275 res.Body.Close() 2276 } 2277 2278 func wantBody(res *http.Response, err error, want string) error { 2279 if err != nil { 2280 return err 2281 } 2282 slurp, err := ioutil.ReadAll(res.Body) 2283 if err != nil { 2284 return fmt.Errorf("error reading body: %v", err) 2285 } 2286 if string(slurp) != want { 2287 return fmt.Errorf("body = %q; want %q", slurp, want) 2288 } 2289 if err := res.Body.Close(); err != nil { 2290 return fmt.Errorf("body Close = %v", err) 2291 } 2292 return nil 2293 } 2294 2295 func newLocalListener(t *testing.T) net.Listener { 2296 ln, err := net.Listen("tcp", "127.0.0.1:0") 2297 if err != nil { 2298 ln, err = net.Listen("tcp6", "[::1]:0") 2299 } 2300 if err != nil { 2301 t.Fatal(err) 2302 } 2303 return ln 2304 } 2305 2306 type countCloseReader struct { 2307 n *int 2308 io.Reader 2309 } 2310 2311 func (cr countCloseReader) Close() error { 2312 (*cr.n)++ 2313 return nil 2314 } 2315 2316 // rgz is a gzip quine that uncompresses to itself. 2317 var rgz = []byte{ 2318 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 2319 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 2320 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 2321 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 2322 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 2323 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 2324 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 2325 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 2326 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 2327 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 2328 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 2329 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 2330 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 2331 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 2332 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 2333 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 2334 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 2335 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 2336 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 2337 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 2338 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 2339 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 2340 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 2341 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 2342 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 2343 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 2344 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 2345 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 2346 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 2347 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 2348 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 2349 0x00, 0x00, 2350 }