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