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