github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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 "context" 17 "crypto/rand" 18 "crypto/tls" 19 "encoding/binary" 20 "errors" 21 "fmt" 22 "internal/nettrace" 23 "internal/testenv" 24 "io" 25 "io/ioutil" 26 "log" 27 "net" 28 . "net/http" 29 "net/http/httptest" 30 "net/http/httptrace" 31 "net/http/httputil" 32 "net/http/internal" 33 "net/url" 34 "os" 35 "reflect" 36 "runtime" 37 "strconv" 38 "strings" 39 "sync" 40 "sync/atomic" 41 "testing" 42 "time" 43 ) 44 45 // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close 46 // and then verify that the final 2 responses get errors back. 47 48 // hostPortHandler writes back the client's "host:port". 49 var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 50 if r.FormValue("close") == "true" { 51 w.Header().Set("Connection", "close") 52 } 53 w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close)) 54 w.Write([]byte(r.RemoteAddr)) 55 }) 56 57 // testCloseConn is a net.Conn tracked by a testConnSet. 58 type testCloseConn struct { 59 net.Conn 60 set *testConnSet 61 } 62 63 func (c *testCloseConn) Close() error { 64 c.set.remove(c) 65 return c.Conn.Close() 66 } 67 68 // testConnSet tracks a set of TCP connections and whether they've 69 // been closed. 70 type testConnSet struct { 71 t *testing.T 72 mu sync.Mutex // guards closed and list 73 closed map[net.Conn]bool 74 list []net.Conn // in order created 75 } 76 77 func (tcs *testConnSet) insert(c net.Conn) { 78 tcs.mu.Lock() 79 defer tcs.mu.Unlock() 80 tcs.closed[c] = false 81 tcs.list = append(tcs.list, c) 82 } 83 84 func (tcs *testConnSet) remove(c net.Conn) { 85 tcs.mu.Lock() 86 defer tcs.mu.Unlock() 87 tcs.closed[c] = true 88 } 89 90 // some tests use this to manage raw tcp connections for later inspection 91 func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) { 92 connSet := &testConnSet{ 93 t: t, 94 closed: make(map[net.Conn]bool), 95 } 96 dial := func(n, addr string) (net.Conn, error) { 97 c, err := net.Dial(n, addr) 98 if err != nil { 99 return nil, err 100 } 101 tc := &testCloseConn{c, connSet} 102 connSet.insert(tc) 103 return tc, nil 104 } 105 return connSet, dial 106 } 107 108 func (tcs *testConnSet) check(t *testing.T) { 109 tcs.mu.Lock() 110 defer tcs.mu.Unlock() 111 for i := 4; i >= 0; i-- { 112 for i, c := range tcs.list { 113 if tcs.closed[c] { 114 continue 115 } 116 if i != 0 { 117 tcs.mu.Unlock() 118 time.Sleep(50 * time.Millisecond) 119 tcs.mu.Lock() 120 continue 121 } 122 t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list)) 123 } 124 } 125 } 126 127 // Two subsequent requests and verify their response is the same. 128 // The response from the server is our own IP:port 129 func TestTransportKeepAlives(t *testing.T) { 130 defer afterTest(t) 131 ts := httptest.NewServer(hostPortHandler) 132 defer ts.Close() 133 134 c := ts.Client() 135 for _, disableKeepAlive := range []bool{false, true} { 136 c.Transport.(*Transport).DisableKeepAlives = disableKeepAlive 137 fetch := func(n int) string { 138 res, err := c.Get(ts.URL) 139 if err != nil { 140 t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err) 141 } 142 body, err := ioutil.ReadAll(res.Body) 143 if err != nil { 144 t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err) 145 } 146 return string(body) 147 } 148 149 body1 := fetch(1) 150 body2 := fetch(2) 151 152 bodiesDiffer := body1 != body2 153 if bodiesDiffer != disableKeepAlive { 154 t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 155 disableKeepAlive, bodiesDiffer, body1, body2) 156 } 157 } 158 } 159 160 func TestTransportConnectionCloseOnResponse(t *testing.T) { 161 defer afterTest(t) 162 ts := httptest.NewServer(hostPortHandler) 163 defer ts.Close() 164 165 connSet, testDial := makeTestDial(t) 166 167 c := ts.Client() 168 tr := c.Transport.(*Transport) 169 tr.Dial = testDial 170 171 for _, connectionClose := range []bool{false, true} { 172 fetch := func(n int) string { 173 req := new(Request) 174 var err error 175 req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose)) 176 if err != nil { 177 t.Fatalf("URL parse error: %v", err) 178 } 179 req.Method = "GET" 180 req.Proto = "HTTP/1.1" 181 req.ProtoMajor = 1 182 req.ProtoMinor = 1 183 184 res, err := c.Do(req) 185 if err != nil { 186 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) 187 } 188 defer res.Body.Close() 189 body, err := ioutil.ReadAll(res.Body) 190 if err != nil { 191 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) 192 } 193 return string(body) 194 } 195 196 body1 := fetch(1) 197 body2 := fetch(2) 198 bodiesDiffer := body1 != body2 199 if bodiesDiffer != connectionClose { 200 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 201 connectionClose, bodiesDiffer, body1, body2) 202 } 203 204 tr.CloseIdleConnections() 205 } 206 207 connSet.check(t) 208 } 209 210 func TestTransportConnectionCloseOnRequest(t *testing.T) { 211 defer afterTest(t) 212 ts := httptest.NewServer(hostPortHandler) 213 defer ts.Close() 214 215 connSet, testDial := makeTestDial(t) 216 217 c := ts.Client() 218 tr := c.Transport.(*Transport) 219 tr.Dial = testDial 220 for _, connectionClose := range []bool{false, true} { 221 fetch := func(n int) string { 222 req := new(Request) 223 var err error 224 req.URL, err = url.Parse(ts.URL) 225 if err != nil { 226 t.Fatalf("URL parse error: %v", err) 227 } 228 req.Method = "GET" 229 req.Proto = "HTTP/1.1" 230 req.ProtoMajor = 1 231 req.ProtoMinor = 1 232 req.Close = connectionClose 233 234 res, err := c.Do(req) 235 if err != nil { 236 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) 237 } 238 if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(connectionClose); got != want { 239 t.Errorf("For connectionClose = %v; handler's X-Saw-Close was %v; want %v", 240 connectionClose, got, !connectionClose) 241 } 242 body, err := ioutil.ReadAll(res.Body) 243 if err != nil { 244 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) 245 } 246 return string(body) 247 } 248 249 body1 := fetch(1) 250 body2 := fetch(2) 251 bodiesDiffer := body1 != body2 252 if bodiesDiffer != connectionClose { 253 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 254 connectionClose, bodiesDiffer, body1, body2) 255 } 256 257 tr.CloseIdleConnections() 258 } 259 260 connSet.check(t) 261 } 262 263 // if the Transport's DisableKeepAlives is set, all requests should 264 // send Connection: close. 265 // HTTP/1-only (Connection: close doesn't exist in h2) 266 func TestTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T) { 267 defer afterTest(t) 268 ts := httptest.NewServer(hostPortHandler) 269 defer ts.Close() 270 271 c := ts.Client() 272 c.Transport.(*Transport).DisableKeepAlives = true 273 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 c := ts.Client() 289 tr := c.Transport.(*Transport) 290 291 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 292 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) 293 } 294 295 resp, err := c.Get(ts.URL) 296 if err != nil { 297 t.Error(err) 298 } 299 ioutil.ReadAll(resp.Body) 300 301 keys := tr.IdleConnKeysForTesting() 302 if e, g := 1, len(keys); e != g { 303 t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g) 304 } 305 306 if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e { 307 t.Errorf("Expected idle cache key %q; got %q", e, keys[0]) 308 } 309 310 tr.CloseIdleConnections() 311 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 312 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) 313 } 314 } 315 316 // Tests that the HTTP transport re-uses connections when a client 317 // reads to the end of a response Body without closing it. 318 func TestTransportReadToEndReusesConn(t *testing.T) { 319 defer afterTest(t) 320 const msg = "foobar" 321 322 var addrSeen map[string]int 323 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 324 addrSeen[r.RemoteAddr]++ 325 if r.URL.Path == "/chunked/" { 326 w.WriteHeader(200) 327 w.(Flusher).Flush() 328 } else { 329 w.Header().Set("Content-Type", strconv.Itoa(len(msg))) 330 w.WriteHeader(200) 331 } 332 w.Write([]byte(msg)) 333 })) 334 defer ts.Close() 335 336 buf := make([]byte, len(msg)) 337 338 for pi, path := range []string{"/content-length/", "/chunked/"} { 339 wantLen := []int{len(msg), -1}[pi] 340 addrSeen = make(map[string]int) 341 for i := 0; i < 3; i++ { 342 res, err := Get(ts.URL + path) 343 if err != nil { 344 t.Errorf("Get %s: %v", path, err) 345 continue 346 } 347 // We want to close this body eventually (before the 348 // defer afterTest at top runs), but not before the 349 // len(addrSeen) check at the bottom of this test, 350 // since Closing this early in the loop would risk 351 // making connections be re-used for the wrong reason. 352 defer res.Body.Close() 353 354 if res.ContentLength != int64(wantLen) { 355 t.Errorf("%s res.ContentLength = %d; want %d", path, res.ContentLength, wantLen) 356 } 357 n, err := res.Body.Read(buf) 358 if n != len(msg) || err != io.EOF { 359 t.Errorf("%s Read = %v, %v; want %d, EOF", path, n, err, len(msg)) 360 } 361 } 362 if len(addrSeen) != 1 { 363 t.Errorf("for %s, server saw %d distinct client addresses; want 1", path, len(addrSeen)) 364 } 365 } 366 } 367 368 func TestTransportMaxPerHostIdleConns(t *testing.T) { 369 defer afterTest(t) 370 resch := make(chan string) 371 gotReq := make(chan bool) 372 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 373 gotReq <- true 374 msg := <-resch 375 _, err := w.Write([]byte(msg)) 376 if err != nil { 377 t.Fatalf("Write: %v", err) 378 } 379 })) 380 defer ts.Close() 381 382 c := ts.Client() 383 tr := c.Transport.(*Transport) 384 maxIdleConnsPerHost := 2 385 tr.MaxIdleConnsPerHost = maxIdleConnsPerHost 386 387 // Start 3 outstanding requests and wait for the server to get them. 388 // Their responses will hang until we write to resch, though. 389 donech := make(chan bool) 390 doReq := func() { 391 resp, err := c.Get(ts.URL) 392 if err != nil { 393 t.Error(err) 394 return 395 } 396 if _, err := ioutil.ReadAll(resp.Body); err != nil { 397 t.Errorf("ReadAll: %v", err) 398 return 399 } 400 donech <- true 401 } 402 go doReq() 403 <-gotReq 404 go doReq() 405 <-gotReq 406 go doReq() 407 <-gotReq 408 409 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 410 t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g) 411 } 412 413 resch <- "res1" 414 <-donech 415 keys := tr.IdleConnKeysForTesting() 416 if e, g := 1, len(keys); e != g { 417 t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g) 418 } 419 cacheKey := "|http|" + ts.Listener.Addr().String() 420 if keys[0] != cacheKey { 421 t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0]) 422 } 423 if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g { 424 t.Errorf("after first response, expected %d idle conns; got %d", e, g) 425 } 426 427 resch <- "res2" 428 <-donech 429 if g, w := tr.IdleConnCountForTesting(cacheKey), 2; g != w { 430 t.Errorf("after second response, idle conns = %d; want %d", g, w) 431 } 432 433 resch <- "res3" 434 <-donech 435 if g, w := tr.IdleConnCountForTesting(cacheKey), maxIdleConnsPerHost; g != w { 436 t.Errorf("after third response, idle conns = %d; want %d", g, w) 437 } 438 } 439 440 func TestTransportRemovesDeadIdleConnections(t *testing.T) { 441 setParallel(t) 442 defer afterTest(t) 443 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 444 io.WriteString(w, r.RemoteAddr) 445 })) 446 defer ts.Close() 447 448 c := ts.Client() 449 tr := c.Transport.(*Transport) 450 451 doReq := func(name string) string { 452 // Do a POST instead of a GET to prevent the Transport's 453 // idempotent request retry logic from kicking in... 454 res, err := c.Post(ts.URL, "", nil) 455 if err != nil { 456 t.Fatalf("%s: %v", name, err) 457 } 458 if res.StatusCode != 200 { 459 t.Fatalf("%s: %v", name, res.Status) 460 } 461 defer res.Body.Close() 462 slurp, err := ioutil.ReadAll(res.Body) 463 if err != nil { 464 t.Fatalf("%s: %v", name, err) 465 } 466 return string(slurp) 467 } 468 469 first := doReq("first") 470 keys1 := tr.IdleConnKeysForTesting() 471 472 ts.CloseClientConnections() 473 474 var keys2 []string 475 if !waitCondition(3*time.Second, 50*time.Millisecond, func() bool { 476 keys2 = tr.IdleConnKeysForTesting() 477 return len(keys2) == 0 478 }) { 479 t.Fatalf("Transport didn't notice idle connection's death.\nbefore: %q\n after: %q\n", keys1, keys2) 480 } 481 482 second := doReq("second") 483 if first == second { 484 t.Errorf("expected a different connection between requests. got %q both times", first) 485 } 486 } 487 488 func TestTransportServerClosingUnexpectedly(t *testing.T) { 489 setParallel(t) 490 defer afterTest(t) 491 ts := httptest.NewServer(hostPortHandler) 492 defer ts.Close() 493 c := ts.Client() 494 495 fetch := func(n, retries int) string { 496 condFatalf := func(format string, arg ...interface{}) { 497 if retries <= 0 { 498 t.Fatalf(format, arg...) 499 } 500 t.Logf("retrying shortly after expected error: "+format, arg...) 501 time.Sleep(time.Second / time.Duration(retries)) 502 } 503 for retries >= 0 { 504 retries-- 505 res, err := c.Get(ts.URL) 506 if err != nil { 507 condFatalf("error in req #%d, GET: %v", n, err) 508 continue 509 } 510 body, err := ioutil.ReadAll(res.Body) 511 if err != nil { 512 condFatalf("error in req #%d, ReadAll: %v", n, err) 513 continue 514 } 515 res.Body.Close() 516 return string(body) 517 } 518 panic("unreachable") 519 } 520 521 body1 := fetch(1, 0) 522 body2 := fetch(2, 0) 523 524 ts.CloseClientConnections() // surprise! 525 526 // This test has an expected race. Sleeping for 25 ms prevents 527 // it on most fast machines, causing the next fetch() call to 528 // succeed quickly. But if we do get errors, fetch() will retry 5 529 // times with some delays between. 530 time.Sleep(25 * time.Millisecond) 531 532 body3 := fetch(3, 5) 533 534 if body1 != body2 { 535 t.Errorf("expected body1 and body2 to be equal") 536 } 537 if body2 == body3 { 538 t.Errorf("expected body2 and body3 to be different") 539 } 540 } 541 542 // Test for https://golang.org/issue/2616 (appropriate issue number) 543 // This fails pretty reliably with GOMAXPROCS=100 or something high. 544 func TestStressSurpriseServerCloses(t *testing.T) { 545 defer afterTest(t) 546 if testing.Short() { 547 t.Skip("skipping test in short mode") 548 } 549 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 550 w.Header().Set("Content-Length", "5") 551 w.Header().Set("Content-Type", "text/plain") 552 w.Write([]byte("Hello")) 553 w.(Flusher).Flush() 554 conn, buf, _ := w.(Hijacker).Hijack() 555 buf.Flush() 556 conn.Close() 557 })) 558 defer ts.Close() 559 c := ts.Client() 560 561 // Do a bunch of traffic from different goroutines. Send to activityc 562 // after each request completes, regardless of whether it failed. 563 // If these are too high, OS X exhausts its ephemeral ports 564 // and hangs waiting for them to transition TCP states. That's 565 // not what we want to test. TODO(bradfitz): use an io.Pipe 566 // dialer for this test instead? 567 const ( 568 numClients = 20 569 reqsPerClient = 25 570 ) 571 activityc := make(chan bool) 572 for i := 0; i < numClients; i++ { 573 go func() { 574 for i := 0; i < reqsPerClient; i++ { 575 res, err := c.Get(ts.URL) 576 if err == nil { 577 // We expect errors since the server is 578 // hanging up on us after telling us to 579 // send more requests, so we don't 580 // actually care what the error is. 581 // But we want to close the body in cases 582 // where we won the race. 583 res.Body.Close() 584 } 585 activityc <- true 586 } 587 }() 588 } 589 590 // Make sure all the request come back, one way or another. 591 for i := 0; i < numClients*reqsPerClient; i++ { 592 select { 593 case <-activityc: 594 case <-time.After(5 * time.Second): 595 t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile") 596 } 597 } 598 } 599 600 // TestTransportHeadResponses verifies that we deal with Content-Lengths 601 // with no bodies properly 602 func TestTransportHeadResponses(t *testing.T) { 603 defer afterTest(t) 604 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 605 if r.Method != "HEAD" { 606 panic("expected HEAD; got " + r.Method) 607 } 608 w.Header().Set("Content-Length", "123") 609 w.WriteHeader(200) 610 })) 611 defer ts.Close() 612 c := ts.Client() 613 614 for i := 0; i < 2; i++ { 615 res, err := c.Head(ts.URL) 616 if err != nil { 617 t.Errorf("error on loop %d: %v", i, err) 618 continue 619 } 620 if e, g := "123", res.Header.Get("Content-Length"); e != g { 621 t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g) 622 } 623 if e, g := int64(123), res.ContentLength; e != g { 624 t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g) 625 } 626 if all, err := ioutil.ReadAll(res.Body); err != nil { 627 t.Errorf("loop %d: Body ReadAll: %v", i, err) 628 } else if len(all) != 0 { 629 t.Errorf("Bogus body %q", all) 630 } 631 } 632 } 633 634 // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding 635 // on responses to HEAD requests. 636 func TestTransportHeadChunkedResponse(t *testing.T) { 637 defer afterTest(t) 638 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 639 if r.Method != "HEAD" { 640 panic("expected HEAD; got " + r.Method) 641 } 642 w.Header().Set("Transfer-Encoding", "chunked") // client should ignore 643 w.Header().Set("x-client-ipport", r.RemoteAddr) 644 w.WriteHeader(200) 645 })) 646 defer ts.Close() 647 c := ts.Client() 648 649 // Ensure that we wait for the readLoop to complete before 650 // calling Head again 651 didRead := make(chan bool) 652 SetReadLoopBeforeNextReadHook(func() { didRead <- true }) 653 defer SetReadLoopBeforeNextReadHook(nil) 654 655 res1, err := c.Head(ts.URL) 656 <-didRead 657 658 if err != nil { 659 t.Fatalf("request 1 error: %v", err) 660 } 661 662 res2, err := c.Head(ts.URL) 663 <-didRead 664 665 if err != nil { 666 t.Fatalf("request 2 error: %v", err) 667 } 668 if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 { 669 t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2) 670 } 671 } 672 673 var roundTripTests = []struct { 674 accept string 675 expectAccept string 676 compressed bool 677 }{ 678 // Requests with no accept-encoding header use transparent compression 679 {"", "gzip", false}, 680 // Requests with other accept-encoding should pass through unmodified 681 {"foo", "foo", false}, 682 // Requests with accept-encoding == gzip should be passed through 683 {"gzip", "gzip", true}, 684 } 685 686 // Test that the modification made to the Request by the RoundTripper is cleaned up 687 func TestRoundTripGzip(t *testing.T) { 688 setParallel(t) 689 defer afterTest(t) 690 const responseBody = "test response body" 691 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 692 accept := req.Header.Get("Accept-Encoding") 693 if expect := req.FormValue("expect_accept"); accept != expect { 694 t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q", 695 req.FormValue("testnum"), accept, expect) 696 } 697 if accept == "gzip" { 698 rw.Header().Set("Content-Encoding", "gzip") 699 gz := gzip.NewWriter(rw) 700 gz.Write([]byte(responseBody)) 701 gz.Close() 702 } else { 703 rw.Header().Set("Content-Encoding", accept) 704 rw.Write([]byte(responseBody)) 705 } 706 })) 707 defer ts.Close() 708 tr := ts.Client().Transport.(*Transport) 709 710 for i, test := range roundTripTests { 711 // Test basic request (no accept-encoding) 712 req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil) 713 if test.accept != "" { 714 req.Header.Set("Accept-Encoding", test.accept) 715 } 716 res, err := tr.RoundTrip(req) 717 var body []byte 718 if test.compressed { 719 var r *gzip.Reader 720 r, err = gzip.NewReader(res.Body) 721 if err != nil { 722 t.Errorf("%d. gzip NewReader: %v", i, err) 723 continue 724 } 725 body, err = ioutil.ReadAll(r) 726 res.Body.Close() 727 } else { 728 body, err = ioutil.ReadAll(res.Body) 729 } 730 if err != nil { 731 t.Errorf("%d. Error: %q", i, err) 732 continue 733 } 734 if g, e := string(body), responseBody; g != e { 735 t.Errorf("%d. body = %q; want %q", i, g, e) 736 } 737 if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e { 738 t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e) 739 } 740 if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e { 741 t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e) 742 } 743 } 744 745 } 746 747 func TestTransportGzip(t *testing.T) { 748 setParallel(t) 749 defer afterTest(t) 750 const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 751 const nRandBytes = 1024 * 1024 752 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 753 if req.Method == "HEAD" { 754 if g := req.Header.Get("Accept-Encoding"); g != "" { 755 t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g) 756 } 757 return 758 } 759 if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e { 760 t.Errorf("Accept-Encoding = %q, want %q", g, e) 761 } 762 rw.Header().Set("Content-Encoding", "gzip") 763 764 var w io.Writer = rw 765 var buf bytes.Buffer 766 if req.FormValue("chunked") == "0" { 767 w = &buf 768 defer io.Copy(rw, &buf) 769 defer func() { 770 rw.Header().Set("Content-Length", strconv.Itoa(buf.Len())) 771 }() 772 } 773 gz := gzip.NewWriter(w) 774 gz.Write([]byte(testString)) 775 if req.FormValue("body") == "large" { 776 io.CopyN(gz, rand.Reader, nRandBytes) 777 } 778 gz.Close() 779 })) 780 defer ts.Close() 781 c := ts.Client() 782 783 for _, chunked := range []string{"1", "0"} { 784 // First fetch something large, but only read some of it. 785 res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked) 786 if err != nil { 787 t.Fatalf("large get: %v", err) 788 } 789 buf := make([]byte, len(testString)) 790 n, err := io.ReadFull(res.Body, buf) 791 if err != nil { 792 t.Fatalf("partial read of large response: size=%d, %v", n, err) 793 } 794 if e, g := testString, string(buf); e != g { 795 t.Errorf("partial read got %q, expected %q", g, e) 796 } 797 res.Body.Close() 798 // Read on the body, even though it's closed 799 n, err = res.Body.Read(buf) 800 if n != 0 || err == nil { 801 t.Errorf("expected error post-closed large Read; got = %d, %v", n, err) 802 } 803 804 // Then something small. 805 res, err = c.Get(ts.URL + "/?chunked=" + chunked) 806 if err != nil { 807 t.Fatal(err) 808 } 809 body, err := ioutil.ReadAll(res.Body) 810 if err != nil { 811 t.Fatal(err) 812 } 813 if g, e := string(body), testString; g != e { 814 t.Fatalf("body = %q; want %q", g, e) 815 } 816 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 817 t.Fatalf("Content-Encoding = %q; want %q", g, e) 818 } 819 820 // Read on the body after it's been fully read: 821 n, err = res.Body.Read(buf) 822 if n != 0 || err == nil { 823 t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err) 824 } 825 res.Body.Close() 826 n, err = res.Body.Read(buf) 827 if n != 0 || err == nil { 828 t.Errorf("expected Read error after Close; got %d, %v", n, err) 829 } 830 } 831 832 // And a HEAD request too, because they're always weird. 833 res, err := c.Head(ts.URL) 834 if err != nil { 835 t.Fatalf("Head: %v", err) 836 } 837 if res.StatusCode != 200 { 838 t.Errorf("Head status=%d; want=200", res.StatusCode) 839 } 840 } 841 842 // If a request has Expect:100-continue header, the request blocks sending body until the first response. 843 // Premature consumption of the request body should not be occurred. 844 func TestTransportExpect100Continue(t *testing.T) { 845 setParallel(t) 846 defer afterTest(t) 847 848 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 849 switch req.URL.Path { 850 case "/100": 851 // This endpoint implicitly responds 100 Continue and reads body. 852 if _, err := io.Copy(ioutil.Discard, req.Body); err != nil { 853 t.Error("Failed to read Body", err) 854 } 855 rw.WriteHeader(StatusOK) 856 case "/200": 857 // Go 1.5 adds Connection: close header if the client expect 858 // continue but not entire request body is consumed. 859 rw.WriteHeader(StatusOK) 860 case "/500": 861 rw.WriteHeader(StatusInternalServerError) 862 case "/keepalive": 863 // This hijacked endpoint responds error without Connection:close. 864 _, bufrw, err := rw.(Hijacker).Hijack() 865 if err != nil { 866 log.Fatal(err) 867 } 868 bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n") 869 bufrw.WriteString("Content-Length: 0\r\n\r\n") 870 bufrw.Flush() 871 case "/timeout": 872 // This endpoint tries to read body without 100 (Continue) response. 873 // After ExpectContinueTimeout, the reading will be started. 874 conn, bufrw, err := rw.(Hijacker).Hijack() 875 if err != nil { 876 log.Fatal(err) 877 } 878 if _, err := io.CopyN(ioutil.Discard, bufrw, req.ContentLength); err != nil { 879 t.Error("Failed to read Body", err) 880 } 881 bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n") 882 bufrw.Flush() 883 conn.Close() 884 } 885 886 })) 887 defer ts.Close() 888 889 tests := []struct { 890 path string 891 body []byte 892 sent int 893 status int 894 }{ 895 {path: "/100", body: []byte("hello"), sent: 5, status: 200}, // Got 100 followed by 200, entire body is sent. 896 {path: "/200", body: []byte("hello"), sent: 0, status: 200}, // Got 200 without 100. body isn't sent. 897 {path: "/500", body: []byte("hello"), sent: 0, status: 500}, // Got 500 without 100. body isn't sent. 898 {path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Although without Connection:close, body isn't sent. 899 {path: "/timeout", body: []byte("hello"), sent: 5, status: 200}, // Timeout exceeded and entire body is sent. 900 } 901 902 c := ts.Client() 903 for i, v := range tests { 904 tr := &Transport{ 905 ExpectContinueTimeout: 2 * time.Second, 906 } 907 defer tr.CloseIdleConnections() 908 c.Transport = tr 909 body := bytes.NewReader(v.body) 910 req, err := NewRequest("PUT", ts.URL+v.path, body) 911 if err != nil { 912 t.Fatal(err) 913 } 914 req.Header.Set("Expect", "100-continue") 915 req.ContentLength = int64(len(v.body)) 916 917 resp, err := c.Do(req) 918 if err != nil { 919 t.Fatal(err) 920 } 921 resp.Body.Close() 922 923 sent := len(v.body) - body.Len() 924 if v.status != resp.StatusCode { 925 t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path) 926 } 927 if v.sent != sent { 928 t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path) 929 } 930 } 931 } 932 933 func TestSocks5Proxy(t *testing.T) { 934 defer afterTest(t) 935 ch := make(chan string, 1) 936 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 937 ch <- "real server" 938 })) 939 defer ts.Close() 940 l := newLocalListener(t) 941 defer l.Close() 942 go func() { 943 defer close(ch) 944 s, err := l.Accept() 945 if err != nil { 946 t.Errorf("socks5 proxy Accept(): %v", err) 947 return 948 } 949 defer s.Close() 950 var buf [22]byte 951 if _, err := io.ReadFull(s, buf[:3]); err != nil { 952 t.Errorf("socks5 proxy initial read: %v", err) 953 return 954 } 955 if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) { 956 t.Errorf("socks5 proxy initial read: got %v, want %v", buf[:3], want) 957 return 958 } 959 if _, err := s.Write([]byte{5, 0}); err != nil { 960 t.Errorf("socks5 proxy initial write: %v", err) 961 return 962 } 963 if _, err := io.ReadFull(s, buf[:4]); err != nil { 964 t.Errorf("socks5 proxy second read: %v", err) 965 return 966 } 967 if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) { 968 t.Errorf("socks5 proxy second read: got %v, want %v", buf[:3], want) 969 return 970 } 971 var ipLen int 972 switch buf[3] { 973 case 1: 974 ipLen = 4 975 case 4: 976 ipLen = 16 977 default: 978 t.Fatalf("socks5 proxy second read: unexpected address type %v", buf[4]) 979 } 980 if _, err := io.ReadFull(s, buf[4:ipLen+6]); err != nil { 981 t.Errorf("socks5 proxy address read: %v", err) 982 return 983 } 984 ip := net.IP(buf[4 : ipLen+4]) 985 port := binary.BigEndian.Uint16(buf[ipLen+4 : ipLen+6]) 986 copy(buf[:3], []byte{5, 0, 0}) 987 if _, err := s.Write(buf[:ipLen+6]); err != nil { 988 t.Errorf("socks5 proxy connect write: %v", err) 989 return 990 } 991 done := make(chan struct{}) 992 srv := &Server{Handler: HandlerFunc(func(w ResponseWriter, r *Request) { 993 done <- struct{}{} 994 })} 995 srv.Serve(&oneConnListener{conn: s}) 996 <-done 997 srv.Shutdown(context.Background()) 998 ch <- fmt.Sprintf("proxy for %s:%d", ip, port) 999 }() 1000 1001 pu, err := url.Parse("socks5://" + l.Addr().String()) 1002 if err != nil { 1003 t.Fatal(err) 1004 } 1005 c := ts.Client() 1006 c.Transport.(*Transport).Proxy = ProxyURL(pu) 1007 if _, err := c.Head(ts.URL); err != nil { 1008 t.Error(err) 1009 } 1010 var got string 1011 select { 1012 case got = <-ch: 1013 case <-time.After(5 * time.Second): 1014 t.Fatal("timeout connecting to socks5 proxy") 1015 } 1016 tsu, err := url.Parse(ts.URL) 1017 if err != nil { 1018 t.Fatal(err) 1019 } 1020 want := "proxy for " + tsu.Host 1021 if got != want { 1022 t.Errorf("got %q, want %q", got, want) 1023 } 1024 } 1025 1026 func TestTransportProxy(t *testing.T) { 1027 defer afterTest(t) 1028 ch := make(chan string, 1) 1029 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1030 ch <- "real server" 1031 })) 1032 defer ts.Close() 1033 proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1034 ch <- "proxy for " + r.URL.String() 1035 })) 1036 defer proxy.Close() 1037 1038 pu, err := url.Parse(proxy.URL) 1039 if err != nil { 1040 t.Fatal(err) 1041 } 1042 c := ts.Client() 1043 c.Transport.(*Transport).Proxy = ProxyURL(pu) 1044 if _, err := c.Head(ts.URL); err != nil { 1045 t.Error(err) 1046 } 1047 var got string 1048 select { 1049 case got = <-ch: 1050 case <-time.After(5 * time.Second): 1051 t.Fatal("timeout connecting to http proxy") 1052 } 1053 want := "proxy for " + ts.URL + "/" 1054 if got != want { 1055 t.Errorf("got %q, want %q", got, want) 1056 } 1057 } 1058 1059 // Issue 16997: test transport dial preserves typed errors 1060 func TestTransportDialPreservesNetOpProxyError(t *testing.T) { 1061 defer afterTest(t) 1062 1063 var errDial = errors.New("some dial error") 1064 1065 tr := &Transport{ 1066 Proxy: func(*Request) (*url.URL, error) { 1067 return url.Parse("http://proxy.fake.tld/") 1068 }, 1069 Dial: func(string, string) (net.Conn, error) { 1070 return nil, errDial 1071 }, 1072 } 1073 defer tr.CloseIdleConnections() 1074 1075 c := &Client{Transport: tr} 1076 req, _ := NewRequest("GET", "http://fake.tld", nil) 1077 res, err := c.Do(req) 1078 if err == nil { 1079 res.Body.Close() 1080 t.Fatal("wanted a non-nil error") 1081 } 1082 1083 uerr, ok := err.(*url.Error) 1084 if !ok { 1085 t.Fatalf("got %T, want *url.Error", err) 1086 } 1087 oe, ok := uerr.Err.(*net.OpError) 1088 if !ok { 1089 t.Fatalf("url.Error.Err = %T; want *net.OpError", uerr.Err) 1090 } 1091 want := &net.OpError{ 1092 Op: "proxyconnect", 1093 Net: "tcp", 1094 Err: errDial, // original error, unwrapped. 1095 } 1096 if !reflect.DeepEqual(oe, want) { 1097 t.Errorf("Got error %#v; want %#v", oe, want) 1098 } 1099 } 1100 1101 // TestTransportGzipRecursive sends a gzip quine and checks that the 1102 // client gets the same value back. This is more cute than anything, 1103 // but checks that we don't recurse forever, and checks that 1104 // Content-Encoding is removed. 1105 func TestTransportGzipRecursive(t *testing.T) { 1106 defer afterTest(t) 1107 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1108 w.Header().Set("Content-Encoding", "gzip") 1109 w.Write(rgz) 1110 })) 1111 defer ts.Close() 1112 1113 c := ts.Client() 1114 res, err := c.Get(ts.URL) 1115 if err != nil { 1116 t.Fatal(err) 1117 } 1118 body, err := ioutil.ReadAll(res.Body) 1119 if err != nil { 1120 t.Fatal(err) 1121 } 1122 if !bytes.Equal(body, rgz) { 1123 t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x", 1124 body, rgz) 1125 } 1126 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 1127 t.Fatalf("Content-Encoding = %q; want %q", g, e) 1128 } 1129 } 1130 1131 // golang.org/issue/7750: request fails when server replies with 1132 // a short gzip body 1133 func TestTransportGzipShort(t *testing.T) { 1134 defer afterTest(t) 1135 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1136 w.Header().Set("Content-Encoding", "gzip") 1137 w.Write([]byte{0x1f, 0x8b}) 1138 })) 1139 defer ts.Close() 1140 1141 c := ts.Client() 1142 res, err := c.Get(ts.URL) 1143 if err != nil { 1144 t.Fatal(err) 1145 } 1146 defer res.Body.Close() 1147 _, err = ioutil.ReadAll(res.Body) 1148 if err == nil { 1149 t.Fatal("Expect an error from reading a body.") 1150 } 1151 if err != io.ErrUnexpectedEOF { 1152 t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err) 1153 } 1154 } 1155 1156 // Wait until number of goroutines is no greater than nmax, or time out. 1157 func waitNumGoroutine(nmax int) int { 1158 nfinal := runtime.NumGoroutine() 1159 for ntries := 10; ntries > 0 && nfinal > nmax; ntries-- { 1160 time.Sleep(50 * time.Millisecond) 1161 runtime.GC() 1162 nfinal = runtime.NumGoroutine() 1163 } 1164 return nfinal 1165 } 1166 1167 // tests that persistent goroutine connections shut down when no longer desired. 1168 func TestTransportPersistConnLeak(t *testing.T) { 1169 // Not parallel: counts goroutines 1170 defer afterTest(t) 1171 1172 const numReq = 25 1173 gotReqCh := make(chan bool, numReq) 1174 unblockCh := make(chan bool, numReq) 1175 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1176 gotReqCh <- true 1177 <-unblockCh 1178 w.Header().Set("Content-Length", "0") 1179 w.WriteHeader(204) 1180 })) 1181 defer ts.Close() 1182 c := ts.Client() 1183 tr := c.Transport.(*Transport) 1184 1185 n0 := runtime.NumGoroutine() 1186 1187 didReqCh := make(chan bool, numReq) 1188 failed := make(chan bool, numReq) 1189 for i := 0; i < numReq; i++ { 1190 go func() { 1191 res, err := c.Get(ts.URL) 1192 didReqCh <- true 1193 if err != nil { 1194 t.Errorf("client fetch error: %v", err) 1195 failed <- true 1196 return 1197 } 1198 res.Body.Close() 1199 }() 1200 } 1201 1202 // Wait for all goroutines to be stuck in the Handler. 1203 for i := 0; i < numReq; i++ { 1204 select { 1205 case <-gotReqCh: 1206 // ok 1207 case <-failed: 1208 close(unblockCh) 1209 return 1210 } 1211 } 1212 1213 nhigh := runtime.NumGoroutine() 1214 1215 // Tell all handlers to unblock and reply. 1216 for i := 0; i < numReq; i++ { 1217 unblockCh <- true 1218 } 1219 1220 // Wait for all HTTP clients to be done. 1221 for i := 0; i < numReq; i++ { 1222 <-didReqCh 1223 } 1224 1225 tr.CloseIdleConnections() 1226 nfinal := waitNumGoroutine(n0 + 5) 1227 1228 growth := nfinal - n0 1229 1230 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 1231 // Previously we were leaking one per numReq. 1232 if int(growth) > 5 { 1233 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 1234 t.Error("too many new goroutines") 1235 } 1236 } 1237 1238 // golang.org/issue/4531: Transport leaks goroutines when 1239 // request.ContentLength is explicitly short 1240 func TestTransportPersistConnLeakShortBody(t *testing.T) { 1241 // Not parallel: measures goroutines. 1242 defer afterTest(t) 1243 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1244 })) 1245 defer ts.Close() 1246 c := ts.Client() 1247 tr := c.Transport.(*Transport) 1248 1249 n0 := runtime.NumGoroutine() 1250 body := []byte("Hello") 1251 for i := 0; i < 20; i++ { 1252 req, err := NewRequest("POST", ts.URL, bytes.NewReader(body)) 1253 if err != nil { 1254 t.Fatal(err) 1255 } 1256 req.ContentLength = int64(len(body) - 2) // explicitly short 1257 _, err = c.Do(req) 1258 if err == nil { 1259 t.Fatal("Expect an error from writing too long of a body.") 1260 } 1261 } 1262 nhigh := runtime.NumGoroutine() 1263 tr.CloseIdleConnections() 1264 nfinal := waitNumGoroutine(n0 + 5) 1265 1266 growth := nfinal - n0 1267 1268 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 1269 // Previously we were leaking one per numReq. 1270 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 1271 if int(growth) > 5 { 1272 t.Error("too many new goroutines") 1273 } 1274 } 1275 1276 // This used to crash; https://golang.org/issue/3266 1277 func TestTransportIdleConnCrash(t *testing.T) { 1278 defer afterTest(t) 1279 var tr *Transport 1280 1281 unblockCh := make(chan bool, 1) 1282 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1283 <-unblockCh 1284 tr.CloseIdleConnections() 1285 })) 1286 defer ts.Close() 1287 c := ts.Client() 1288 tr = c.Transport.(*Transport) 1289 1290 didreq := make(chan bool) 1291 go func() { 1292 res, err := c.Get(ts.URL) 1293 if err != nil { 1294 t.Error(err) 1295 } else { 1296 res.Body.Close() // returns idle conn 1297 } 1298 didreq <- true 1299 }() 1300 unblockCh <- true 1301 <-didreq 1302 } 1303 1304 // Test that the transport doesn't close the TCP connection early, 1305 // before the response body has been read. This was a regression 1306 // which sadly lacked a triggering test. The large response body made 1307 // the old race easier to trigger. 1308 func TestIssue3644(t *testing.T) { 1309 defer afterTest(t) 1310 const numFoos = 5000 1311 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1312 w.Header().Set("Connection", "close") 1313 for i := 0; i < numFoos; i++ { 1314 w.Write([]byte("foo ")) 1315 } 1316 })) 1317 defer ts.Close() 1318 c := ts.Client() 1319 res, err := c.Get(ts.URL) 1320 if err != nil { 1321 t.Fatal(err) 1322 } 1323 defer res.Body.Close() 1324 bs, err := ioutil.ReadAll(res.Body) 1325 if err != nil { 1326 t.Fatal(err) 1327 } 1328 if len(bs) != numFoos*len("foo ") { 1329 t.Errorf("unexpected response length") 1330 } 1331 } 1332 1333 // Test that a client receives a server's reply, even if the server doesn't read 1334 // the entire request body. 1335 func TestIssue3595(t *testing.T) { 1336 setParallel(t) 1337 defer afterTest(t) 1338 const deniedMsg = "sorry, denied." 1339 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1340 Error(w, deniedMsg, StatusUnauthorized) 1341 })) 1342 defer ts.Close() 1343 c := ts.Client() 1344 res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a')) 1345 if err != nil { 1346 t.Errorf("Post: %v", err) 1347 return 1348 } 1349 got, err := ioutil.ReadAll(res.Body) 1350 if err != nil { 1351 t.Fatalf("Body ReadAll: %v", err) 1352 } 1353 if !strings.Contains(string(got), deniedMsg) { 1354 t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg) 1355 } 1356 } 1357 1358 // From https://golang.org/issue/4454 , 1359 // "client fails to handle requests with no body and chunked encoding" 1360 func TestChunkedNoContent(t *testing.T) { 1361 defer afterTest(t) 1362 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1363 w.WriteHeader(StatusNoContent) 1364 })) 1365 defer ts.Close() 1366 1367 c := ts.Client() 1368 for _, closeBody := range []bool{true, false} { 1369 const n = 4 1370 for i := 1; i <= n; i++ { 1371 res, err := c.Get(ts.URL) 1372 if err != nil { 1373 t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err) 1374 } else { 1375 if closeBody { 1376 res.Body.Close() 1377 } 1378 } 1379 } 1380 } 1381 } 1382 1383 func TestTransportConcurrency(t *testing.T) { 1384 // Not parallel: uses global test hooks. 1385 defer afterTest(t) 1386 maxProcs, numReqs := 16, 500 1387 if testing.Short() { 1388 maxProcs, numReqs = 4, 50 1389 } 1390 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1391 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1392 fmt.Fprintf(w, "%v", r.FormValue("echo")) 1393 })) 1394 defer ts.Close() 1395 1396 var wg sync.WaitGroup 1397 wg.Add(numReqs) 1398 1399 // Due to the Transport's "socket late binding" (see 1400 // idleConnCh in transport.go), the numReqs HTTP requests 1401 // below can finish with a dial still outstanding. To keep 1402 // the leak checker happy, keep track of pending dials and 1403 // wait for them to finish (and be closed or returned to the 1404 // idle pool) before we close idle connections. 1405 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done) 1406 defer SetPendingDialHooks(nil, nil) 1407 1408 c := ts.Client() 1409 reqs := make(chan string) 1410 defer close(reqs) 1411 1412 for i := 0; i < maxProcs*2; i++ { 1413 go func() { 1414 for req := range reqs { 1415 res, err := c.Get(ts.URL + "/?echo=" + req) 1416 if err != nil { 1417 t.Errorf("error on req %s: %v", req, err) 1418 wg.Done() 1419 continue 1420 } 1421 all, err := ioutil.ReadAll(res.Body) 1422 if err != nil { 1423 t.Errorf("read error on req %s: %v", req, err) 1424 wg.Done() 1425 continue 1426 } 1427 if string(all) != req { 1428 t.Errorf("body of req %s = %q; want %q", req, all, req) 1429 } 1430 res.Body.Close() 1431 wg.Done() 1432 } 1433 }() 1434 } 1435 for i := 0; i < numReqs; i++ { 1436 reqs <- fmt.Sprintf("request-%d", i) 1437 } 1438 wg.Wait() 1439 } 1440 1441 func TestIssue4191_InfiniteGetTimeout(t *testing.T) { 1442 setParallel(t) 1443 defer afterTest(t) 1444 const debug = false 1445 mux := NewServeMux() 1446 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1447 io.Copy(w, neverEnding('a')) 1448 }) 1449 ts := httptest.NewServer(mux) 1450 defer ts.Close() 1451 timeout := 100 * time.Millisecond 1452 1453 c := ts.Client() 1454 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) { 1455 conn, err := net.Dial(n, addr) 1456 if err != nil { 1457 return nil, err 1458 } 1459 conn.SetDeadline(time.Now().Add(timeout)) 1460 if debug { 1461 conn = NewLoggingConn("client", conn) 1462 } 1463 return conn, nil 1464 } 1465 1466 getFailed := false 1467 nRuns := 5 1468 if testing.Short() { 1469 nRuns = 1 1470 } 1471 for i := 0; i < nRuns; i++ { 1472 if debug { 1473 println("run", i+1, "of", nRuns) 1474 } 1475 sres, err := c.Get(ts.URL + "/get") 1476 if err != nil { 1477 if !getFailed { 1478 // Make the timeout longer, once. 1479 getFailed = true 1480 t.Logf("increasing timeout") 1481 i-- 1482 timeout *= 10 1483 continue 1484 } 1485 t.Errorf("Error issuing GET: %v", err) 1486 break 1487 } 1488 _, err = io.Copy(ioutil.Discard, sres.Body) 1489 if err == nil { 1490 t.Errorf("Unexpected successful copy") 1491 break 1492 } 1493 } 1494 if debug { 1495 println("tests complete; waiting for handlers to finish") 1496 } 1497 } 1498 1499 func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) { 1500 setParallel(t) 1501 defer afterTest(t) 1502 const debug = false 1503 mux := NewServeMux() 1504 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1505 io.Copy(w, neverEnding('a')) 1506 }) 1507 mux.HandleFunc("/put", func(w ResponseWriter, r *Request) { 1508 defer r.Body.Close() 1509 io.Copy(ioutil.Discard, r.Body) 1510 }) 1511 ts := httptest.NewServer(mux) 1512 timeout := 100 * time.Millisecond 1513 1514 c := ts.Client() 1515 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) { 1516 conn, err := net.Dial(n, addr) 1517 if err != nil { 1518 return nil, err 1519 } 1520 conn.SetDeadline(time.Now().Add(timeout)) 1521 if debug { 1522 conn = NewLoggingConn("client", conn) 1523 } 1524 return conn, nil 1525 } 1526 1527 getFailed := false 1528 nRuns := 5 1529 if testing.Short() { 1530 nRuns = 1 1531 } 1532 for i := 0; i < nRuns; i++ { 1533 if debug { 1534 println("run", i+1, "of", nRuns) 1535 } 1536 sres, err := c.Get(ts.URL + "/get") 1537 if err != nil { 1538 if !getFailed { 1539 // Make the timeout longer, once. 1540 getFailed = true 1541 t.Logf("increasing timeout") 1542 i-- 1543 timeout *= 10 1544 continue 1545 } 1546 t.Errorf("Error issuing GET: %v", err) 1547 break 1548 } 1549 req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body) 1550 _, err = c.Do(req) 1551 if err == nil { 1552 sres.Body.Close() 1553 t.Errorf("Unexpected successful PUT") 1554 break 1555 } 1556 sres.Body.Close() 1557 } 1558 if debug { 1559 println("tests complete; waiting for handlers to finish") 1560 } 1561 ts.Close() 1562 } 1563 1564 func TestTransportResponseHeaderTimeout(t *testing.T) { 1565 setParallel(t) 1566 defer afterTest(t) 1567 if testing.Short() { 1568 t.Skip("skipping timeout test in -short mode") 1569 } 1570 inHandler := make(chan bool, 1) 1571 mux := NewServeMux() 1572 mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) { 1573 inHandler <- true 1574 }) 1575 mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) { 1576 inHandler <- true 1577 time.Sleep(2 * time.Second) 1578 }) 1579 ts := httptest.NewServer(mux) 1580 defer ts.Close() 1581 1582 c := ts.Client() 1583 c.Transport.(*Transport).ResponseHeaderTimeout = 500 * time.Millisecond 1584 1585 tests := []struct { 1586 path string 1587 want int 1588 wantErr string 1589 }{ 1590 {path: "/fast", want: 200}, 1591 {path: "/slow", wantErr: "timeout awaiting response headers"}, 1592 {path: "/fast", want: 200}, 1593 } 1594 for i, tt := range tests { 1595 req, _ := NewRequest("GET", ts.URL+tt.path, nil) 1596 req = req.WithT(t) 1597 res, err := c.Do(req) 1598 select { 1599 case <-inHandler: 1600 case <-time.After(5 * time.Second): 1601 t.Errorf("never entered handler for test index %d, %s", i, tt.path) 1602 continue 1603 } 1604 if err != nil { 1605 uerr, ok := err.(*url.Error) 1606 if !ok { 1607 t.Errorf("error is not an url.Error; got: %#v", err) 1608 continue 1609 } 1610 nerr, ok := uerr.Err.(net.Error) 1611 if !ok { 1612 t.Errorf("error does not satisfy net.Error interface; got: %#v", err) 1613 continue 1614 } 1615 if !nerr.Timeout() { 1616 t.Errorf("want timeout error; got: %q", nerr) 1617 continue 1618 } 1619 if strings.Contains(err.Error(), tt.wantErr) { 1620 continue 1621 } 1622 t.Errorf("%d. unexpected error: %v", i, err) 1623 continue 1624 } 1625 if tt.wantErr != "" { 1626 t.Errorf("%d. no error. expected error: %v", i, tt.wantErr) 1627 continue 1628 } 1629 if res.StatusCode != tt.want { 1630 t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want) 1631 } 1632 } 1633 } 1634 1635 func TestTransportCancelRequest(t *testing.T) { 1636 setParallel(t) 1637 defer afterTest(t) 1638 if testing.Short() { 1639 t.Skip("skipping test in -short mode") 1640 } 1641 unblockc := make(chan bool) 1642 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1643 fmt.Fprintf(w, "Hello") 1644 w.(Flusher).Flush() // send headers and some body 1645 <-unblockc 1646 })) 1647 defer ts.Close() 1648 defer close(unblockc) 1649 1650 c := ts.Client() 1651 tr := c.Transport.(*Transport) 1652 1653 req, _ := NewRequest("GET", ts.URL, nil) 1654 res, err := c.Do(req) 1655 if err != nil { 1656 t.Fatal(err) 1657 } 1658 go func() { 1659 time.Sleep(1 * time.Second) 1660 tr.CancelRequest(req) 1661 }() 1662 t0 := time.Now() 1663 body, err := ioutil.ReadAll(res.Body) 1664 d := time.Since(t0) 1665 1666 if err != ExportErrRequestCanceled { 1667 t.Errorf("Body.Read error = %v; want errRequestCanceled", err) 1668 } 1669 if string(body) != "Hello" { 1670 t.Errorf("Body = %q; want Hello", body) 1671 } 1672 if d < 500*time.Millisecond { 1673 t.Errorf("expected ~1 second delay; got %v", d) 1674 } 1675 // Verify no outstanding requests after readLoop/writeLoop 1676 // goroutines shut down. 1677 for tries := 5; tries > 0; tries-- { 1678 n := tr.NumPendingRequestsForTesting() 1679 if n == 0 { 1680 break 1681 } 1682 time.Sleep(100 * time.Millisecond) 1683 if tries == 1 { 1684 t.Errorf("pending requests = %d; want 0", n) 1685 } 1686 } 1687 } 1688 1689 func TestTransportCancelRequestInDial(t *testing.T) { 1690 defer afterTest(t) 1691 if testing.Short() { 1692 t.Skip("skipping test in -short mode") 1693 } 1694 var logbuf bytes.Buffer 1695 eventLog := log.New(&logbuf, "", 0) 1696 1697 unblockDial := make(chan bool) 1698 defer close(unblockDial) 1699 1700 inDial := make(chan bool) 1701 tr := &Transport{ 1702 Dial: func(network, addr string) (net.Conn, error) { 1703 eventLog.Println("dial: blocking") 1704 inDial <- true 1705 <-unblockDial 1706 return nil, errors.New("nope") 1707 }, 1708 } 1709 cl := &Client{Transport: tr} 1710 gotres := make(chan bool) 1711 req, _ := NewRequest("GET", "http://something.no-network.tld/", nil) 1712 go func() { 1713 _, err := cl.Do(req) 1714 eventLog.Printf("Get = %v", err) 1715 gotres <- true 1716 }() 1717 1718 select { 1719 case <-inDial: 1720 case <-time.After(5 * time.Second): 1721 t.Fatal("timeout; never saw blocking dial") 1722 } 1723 1724 eventLog.Printf("canceling") 1725 tr.CancelRequest(req) 1726 tr.CancelRequest(req) // used to panic on second call 1727 1728 select { 1729 case <-gotres: 1730 case <-time.After(5 * time.Second): 1731 panic("hang. events are: " + logbuf.String()) 1732 } 1733 1734 got := logbuf.String() 1735 want := `dial: blocking 1736 canceling 1737 Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection 1738 ` 1739 if got != want { 1740 t.Errorf("Got events:\n%s\nWant:\n%s", got, want) 1741 } 1742 } 1743 1744 func TestCancelRequestWithChannel(t *testing.T) { 1745 setParallel(t) 1746 defer afterTest(t) 1747 if testing.Short() { 1748 t.Skip("skipping test in -short mode") 1749 } 1750 unblockc := make(chan bool) 1751 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1752 fmt.Fprintf(w, "Hello") 1753 w.(Flusher).Flush() // send headers and some body 1754 <-unblockc 1755 })) 1756 defer ts.Close() 1757 defer close(unblockc) 1758 1759 c := ts.Client() 1760 tr := c.Transport.(*Transport) 1761 1762 req, _ := NewRequest("GET", ts.URL, nil) 1763 ch := make(chan struct{}) 1764 req.Cancel = ch 1765 1766 res, err := c.Do(req) 1767 if err != nil { 1768 t.Fatal(err) 1769 } 1770 go func() { 1771 time.Sleep(1 * time.Second) 1772 close(ch) 1773 }() 1774 t0 := time.Now() 1775 body, err := ioutil.ReadAll(res.Body) 1776 d := time.Since(t0) 1777 1778 if err != ExportErrRequestCanceled { 1779 t.Errorf("Body.Read error = %v; want errRequestCanceled", err) 1780 } 1781 if string(body) != "Hello" { 1782 t.Errorf("Body = %q; want Hello", body) 1783 } 1784 if d < 500*time.Millisecond { 1785 t.Errorf("expected ~1 second delay; got %v", d) 1786 } 1787 // Verify no outstanding requests after readLoop/writeLoop 1788 // goroutines shut down. 1789 for tries := 5; tries > 0; tries-- { 1790 n := tr.NumPendingRequestsForTesting() 1791 if n == 0 { 1792 break 1793 } 1794 time.Sleep(100 * time.Millisecond) 1795 if tries == 1 { 1796 t.Errorf("pending requests = %d; want 0", n) 1797 } 1798 } 1799 } 1800 1801 func TestCancelRequestWithChannelBeforeDo_Cancel(t *testing.T) { 1802 testCancelRequestWithChannelBeforeDo(t, false) 1803 } 1804 func TestCancelRequestWithChannelBeforeDo_Context(t *testing.T) { 1805 testCancelRequestWithChannelBeforeDo(t, true) 1806 } 1807 func testCancelRequestWithChannelBeforeDo(t *testing.T, withCtx bool) { 1808 setParallel(t) 1809 defer afterTest(t) 1810 unblockc := make(chan bool) 1811 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1812 <-unblockc 1813 })) 1814 defer ts.Close() 1815 defer close(unblockc) 1816 1817 c := ts.Client() 1818 1819 req, _ := NewRequest("GET", ts.URL, nil) 1820 if withCtx { 1821 ctx, cancel := context.WithCancel(context.Background()) 1822 cancel() 1823 req = req.WithContext(ctx) 1824 } else { 1825 ch := make(chan struct{}) 1826 req.Cancel = ch 1827 close(ch) 1828 } 1829 1830 _, err := c.Do(req) 1831 if ue, ok := err.(*url.Error); ok { 1832 err = ue.Err 1833 } 1834 if withCtx { 1835 if err != context.Canceled { 1836 t.Errorf("Do error = %v; want %v", err, context.Canceled) 1837 } 1838 } else { 1839 if err == nil || !strings.Contains(err.Error(), "canceled") { 1840 t.Errorf("Do error = %v; want cancelation", err) 1841 } 1842 } 1843 } 1844 1845 // Issue 11020. The returned error message should be errRequestCanceled 1846 func TestTransportCancelBeforeResponseHeaders(t *testing.T) { 1847 defer afterTest(t) 1848 1849 serverConnCh := make(chan net.Conn, 1) 1850 tr := &Transport{ 1851 Dial: func(network, addr string) (net.Conn, error) { 1852 cc, sc := net.Pipe() 1853 serverConnCh <- sc 1854 return cc, nil 1855 }, 1856 } 1857 defer tr.CloseIdleConnections() 1858 errc := make(chan error, 1) 1859 req, _ := NewRequest("GET", "http://example.com/", nil) 1860 go func() { 1861 _, err := tr.RoundTrip(req) 1862 errc <- err 1863 }() 1864 1865 sc := <-serverConnCh 1866 verb := make([]byte, 3) 1867 if _, err := io.ReadFull(sc, verb); err != nil { 1868 t.Errorf("Error reading HTTP verb from server: %v", err) 1869 } 1870 if string(verb) != "GET" { 1871 t.Errorf("server received %q; want GET", verb) 1872 } 1873 defer sc.Close() 1874 1875 tr.CancelRequest(req) 1876 1877 err := <-errc 1878 if err == nil { 1879 t.Fatalf("unexpected success from RoundTrip") 1880 } 1881 if err != ExportErrRequestCanceled { 1882 t.Errorf("RoundTrip error = %v; want ExportErrRequestCanceled", err) 1883 } 1884 } 1885 1886 // golang.org/issue/3672 -- Client can't close HTTP stream 1887 // Calling Close on a Response.Body used to just read until EOF. 1888 // Now it actually closes the TCP connection. 1889 func TestTransportCloseResponseBody(t *testing.T) { 1890 defer afterTest(t) 1891 writeErr := make(chan error, 1) 1892 msg := []byte("young\n") 1893 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1894 for { 1895 _, err := w.Write(msg) 1896 if err != nil { 1897 writeErr <- err 1898 return 1899 } 1900 w.(Flusher).Flush() 1901 } 1902 })) 1903 defer ts.Close() 1904 1905 c := ts.Client() 1906 tr := c.Transport.(*Transport) 1907 1908 req, _ := NewRequest("GET", ts.URL, nil) 1909 defer tr.CancelRequest(req) 1910 1911 res, err := c.Do(req) 1912 if err != nil { 1913 t.Fatal(err) 1914 } 1915 1916 const repeats = 3 1917 buf := make([]byte, len(msg)*repeats) 1918 want := bytes.Repeat(msg, repeats) 1919 1920 _, err = io.ReadFull(res.Body, buf) 1921 if err != nil { 1922 t.Fatal(err) 1923 } 1924 if !bytes.Equal(buf, want) { 1925 t.Fatalf("read %q; want %q", buf, want) 1926 } 1927 didClose := make(chan error, 1) 1928 go func() { 1929 didClose <- res.Body.Close() 1930 }() 1931 select { 1932 case err := <-didClose: 1933 if err != nil { 1934 t.Errorf("Close = %v", err) 1935 } 1936 case <-time.After(10 * time.Second): 1937 t.Fatal("too long waiting for close") 1938 } 1939 select { 1940 case err := <-writeErr: 1941 if err == nil { 1942 t.Errorf("expected non-nil write error") 1943 } 1944 case <-time.After(10 * time.Second): 1945 t.Fatal("too long waiting for write error") 1946 } 1947 } 1948 1949 type fooProto struct{} 1950 1951 func (fooProto) RoundTrip(req *Request) (*Response, error) { 1952 res := &Response{ 1953 Status: "200 OK", 1954 StatusCode: 200, 1955 Header: make(Header), 1956 Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())), 1957 } 1958 return res, nil 1959 } 1960 1961 func TestTransportAltProto(t *testing.T) { 1962 defer afterTest(t) 1963 tr := &Transport{} 1964 c := &Client{Transport: tr} 1965 tr.RegisterProtocol("foo", fooProto{}) 1966 res, err := c.Get("foo://bar.com/path") 1967 if err != nil { 1968 t.Fatal(err) 1969 } 1970 bodyb, err := ioutil.ReadAll(res.Body) 1971 if err != nil { 1972 t.Fatal(err) 1973 } 1974 body := string(bodyb) 1975 if e := "You wanted foo://bar.com/path"; body != e { 1976 t.Errorf("got response %q, want %q", body, e) 1977 } 1978 } 1979 1980 func TestTransportNoHost(t *testing.T) { 1981 defer afterTest(t) 1982 tr := &Transport{} 1983 _, err := tr.RoundTrip(&Request{ 1984 Header: make(Header), 1985 URL: &url.URL{ 1986 Scheme: "http", 1987 }, 1988 }) 1989 want := "http: no Host in request URL" 1990 if got := fmt.Sprint(err); got != want { 1991 t.Errorf("error = %v; want %q", err, want) 1992 } 1993 } 1994 1995 // Issue 13311 1996 func TestTransportEmptyMethod(t *testing.T) { 1997 req, _ := NewRequest("GET", "http://foo.com/", nil) 1998 req.Method = "" // docs say "For client requests an empty string means GET" 1999 got, err := httputil.DumpRequestOut(req, false) // DumpRequestOut uses Transport 2000 if err != nil { 2001 t.Fatal(err) 2002 } 2003 if !strings.Contains(string(got), "GET ") { 2004 t.Fatalf("expected substring 'GET '; got: %s", got) 2005 } 2006 } 2007 2008 func TestTransportSocketLateBinding(t *testing.T) { 2009 setParallel(t) 2010 defer afterTest(t) 2011 2012 mux := NewServeMux() 2013 fooGate := make(chan bool, 1) 2014 mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) { 2015 w.Header().Set("foo-ipport", r.RemoteAddr) 2016 w.(Flusher).Flush() 2017 <-fooGate 2018 }) 2019 mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) { 2020 w.Header().Set("bar-ipport", r.RemoteAddr) 2021 }) 2022 ts := httptest.NewServer(mux) 2023 defer ts.Close() 2024 2025 dialGate := make(chan bool, 1) 2026 c := ts.Client() 2027 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) { 2028 if <-dialGate { 2029 return net.Dial(n, addr) 2030 } 2031 return nil, errors.New("manually closed") 2032 } 2033 2034 dialGate <- true // only allow one dial 2035 fooRes, err := c.Get(ts.URL + "/foo") 2036 if err != nil { 2037 t.Fatal(err) 2038 } 2039 fooAddr := fooRes.Header.Get("foo-ipport") 2040 if fooAddr == "" { 2041 t.Fatal("No addr on /foo request") 2042 } 2043 time.AfterFunc(200*time.Millisecond, func() { 2044 // let the foo response finish so we can use its 2045 // connection for /bar 2046 fooGate <- true 2047 io.Copy(ioutil.Discard, fooRes.Body) 2048 fooRes.Body.Close() 2049 }) 2050 2051 barRes, err := c.Get(ts.URL + "/bar") 2052 if err != nil { 2053 t.Fatal(err) 2054 } 2055 barAddr := barRes.Header.Get("bar-ipport") 2056 if barAddr != fooAddr { 2057 t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr) 2058 } 2059 barRes.Body.Close() 2060 dialGate <- false 2061 } 2062 2063 // Issue 2184 2064 func TestTransportReading100Continue(t *testing.T) { 2065 defer afterTest(t) 2066 2067 const numReqs = 5 2068 reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) } 2069 reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) } 2070 2071 send100Response := func(w *io.PipeWriter, r *io.PipeReader) { 2072 defer w.Close() 2073 defer r.Close() 2074 br := bufio.NewReader(r) 2075 n := 0 2076 for { 2077 n++ 2078 req, err := ReadRequest(br) 2079 if err == io.EOF { 2080 return 2081 } 2082 if err != nil { 2083 t.Error(err) 2084 return 2085 } 2086 slurp, err := ioutil.ReadAll(req.Body) 2087 if err != nil { 2088 t.Errorf("Server request body slurp: %v", err) 2089 return 2090 } 2091 id := req.Header.Get("Request-Id") 2092 resCode := req.Header.Get("X-Want-Response-Code") 2093 if resCode == "" { 2094 resCode = "100 Continue" 2095 if string(slurp) != reqBody(n) { 2096 t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n)) 2097 } 2098 } 2099 body := fmt.Sprintf("Response number %d", n) 2100 v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s 2101 Date: Thu, 28 Feb 2013 17:55:41 GMT 2102 2103 HTTP/1.1 200 OK 2104 Content-Type: text/html 2105 Echo-Request-Id: %s 2106 Content-Length: %d 2107 2108 %s`, resCode, id, len(body), body), "\n", "\r\n", -1)) 2109 w.Write(v) 2110 if id == reqID(numReqs) { 2111 return 2112 } 2113 } 2114 2115 } 2116 2117 tr := &Transport{ 2118 Dial: func(n, addr string) (net.Conn, error) { 2119 sr, sw := io.Pipe() // server read/write 2120 cr, cw := io.Pipe() // client read/write 2121 conn := &rwTestConn{ 2122 Reader: cr, 2123 Writer: sw, 2124 closeFunc: func() error { 2125 sw.Close() 2126 cw.Close() 2127 return nil 2128 }, 2129 } 2130 go send100Response(cw, sr) 2131 return conn, nil 2132 }, 2133 DisableKeepAlives: false, 2134 } 2135 defer tr.CloseIdleConnections() 2136 c := &Client{Transport: tr} 2137 2138 testResponse := func(req *Request, name string, wantCode int) { 2139 res, err := c.Do(req) 2140 if err != nil { 2141 t.Fatalf("%s: Do: %v", name, err) 2142 } 2143 if res.StatusCode != wantCode { 2144 t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode) 2145 } 2146 if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack { 2147 t.Errorf("%s: response id %q != request id %q", name, idBack, id) 2148 } 2149 _, err = ioutil.ReadAll(res.Body) 2150 if err != nil { 2151 t.Fatalf("%s: Slurp error: %v", name, err) 2152 } 2153 } 2154 2155 // Few 100 responses, making sure we're not off-by-one. 2156 for i := 1; i <= numReqs; i++ { 2157 req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i))) 2158 req.Header.Set("Request-Id", reqID(i)) 2159 testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200) 2160 } 2161 2162 // And some other informational 1xx but non-100 responses, to test 2163 // we return them but don't re-use the connection. 2164 for i := 1; i <= numReqs; i++ { 2165 req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i))) 2166 req.Header.Set("X-Want-Response-Code", "123 Sesame Street") 2167 testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123) 2168 } 2169 } 2170 2171 type proxyFromEnvTest struct { 2172 req string // URL to fetch; blank means "http://example.com" 2173 2174 env string // HTTP_PROXY 2175 httpsenv string // HTTPS_PROXY 2176 noenv string // NO_PROXY 2177 reqmeth string // REQUEST_METHOD 2178 2179 want string 2180 wanterr error 2181 } 2182 2183 func (t proxyFromEnvTest) String() string { 2184 var buf bytes.Buffer 2185 space := func() { 2186 if buf.Len() > 0 { 2187 buf.WriteByte(' ') 2188 } 2189 } 2190 if t.env != "" { 2191 fmt.Fprintf(&buf, "http_proxy=%q", t.env) 2192 } 2193 if t.httpsenv != "" { 2194 space() 2195 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv) 2196 } 2197 if t.noenv != "" { 2198 space() 2199 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv) 2200 } 2201 if t.reqmeth != "" { 2202 space() 2203 fmt.Fprintf(&buf, "request_method=%q", t.reqmeth) 2204 } 2205 req := "http://example.com" 2206 if t.req != "" { 2207 req = t.req 2208 } 2209 space() 2210 fmt.Fprintf(&buf, "req=%q", req) 2211 return strings.TrimSpace(buf.String()) 2212 } 2213 2214 var proxyFromEnvTests = []proxyFromEnvTest{ 2215 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2216 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"}, 2217 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"}, 2218 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"}, 2219 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2220 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"}, 2221 {env: "socks5://127.0.0.1", want: "socks5://127.0.0.1"}, 2222 2223 // Don't use secure for http 2224 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"}, 2225 // Use secure for https. 2226 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"}, 2227 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"}, 2228 2229 // Issue 16405: don't use HTTP_PROXY in a CGI environment, 2230 // where HTTP_PROXY can be attacker-controlled. 2231 {env: "http://10.1.2.3:8080", reqmeth: "POST", 2232 want: "<nil>", 2233 wanterr: errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")}, 2234 2235 {want: "<nil>"}, 2236 2237 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2238 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2239 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2240 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"}, 2241 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2242 } 2243 2244 func TestProxyFromEnvironment(t *testing.T) { 2245 ResetProxyEnv() 2246 defer ResetProxyEnv() 2247 for _, tt := range proxyFromEnvTests { 2248 os.Setenv("HTTP_PROXY", tt.env) 2249 os.Setenv("HTTPS_PROXY", tt.httpsenv) 2250 os.Setenv("NO_PROXY", tt.noenv) 2251 os.Setenv("REQUEST_METHOD", tt.reqmeth) 2252 ResetCachedEnvironment() 2253 reqURL := tt.req 2254 if reqURL == "" { 2255 reqURL = "http://example.com" 2256 } 2257 req, _ := NewRequest("GET", reqURL, nil) 2258 url, err := ProxyFromEnvironment(req) 2259 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 2260 t.Errorf("%v: got error = %q, want %q", tt, g, e) 2261 continue 2262 } 2263 if got := fmt.Sprintf("%s", url); got != tt.want { 2264 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 2265 } 2266 } 2267 } 2268 2269 func TestIdleConnChannelLeak(t *testing.T) { 2270 // Not parallel: uses global test hooks. 2271 var mu sync.Mutex 2272 var n int 2273 2274 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2275 mu.Lock() 2276 n++ 2277 mu.Unlock() 2278 })) 2279 defer ts.Close() 2280 2281 const nReqs = 5 2282 didRead := make(chan bool, nReqs) 2283 SetReadLoopBeforeNextReadHook(func() { didRead <- true }) 2284 defer SetReadLoopBeforeNextReadHook(nil) 2285 2286 c := ts.Client() 2287 tr := c.Transport.(*Transport) 2288 tr.Dial = func(netw, addr string) (net.Conn, error) { 2289 return net.Dial(netw, ts.Listener.Addr().String()) 2290 } 2291 2292 // First, without keep-alives. 2293 for _, disableKeep := range []bool{true, false} { 2294 tr.DisableKeepAlives = disableKeep 2295 for i := 0; i < nReqs; i++ { 2296 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i)) 2297 if err != nil { 2298 t.Fatal(err) 2299 } 2300 // Note: no res.Body.Close is needed here, since the 2301 // response Content-Length is zero. Perhaps the test 2302 // should be more explicit and use a HEAD, but tests 2303 // elsewhere guarantee that zero byte responses generate 2304 // a "Content-Length: 0" instead of chunking. 2305 } 2306 2307 // At this point, each of the 5 Transport.readLoop goroutines 2308 // are scheduling noting that there are no response bodies (see 2309 // earlier comment), and are then calling putIdleConn, which 2310 // decrements this count. Usually that happens quickly, which is 2311 // why this test has seemed to work for ages. But it's still 2312 // racey: we have wait for them to finish first. See Issue 10427 2313 for i := 0; i < nReqs; i++ { 2314 <-didRead 2315 } 2316 2317 if got := tr.IdleConnChMapSizeForTesting(); got != 0 { 2318 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got) 2319 } 2320 } 2321 } 2322 2323 // Verify the status quo: that the Client.Post function coerces its 2324 // body into a ReadCloser if it's a Closer, and that the Transport 2325 // then closes it. 2326 func TestTransportClosesRequestBody(t *testing.T) { 2327 defer afterTest(t) 2328 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2329 io.Copy(ioutil.Discard, r.Body) 2330 })) 2331 defer ts.Close() 2332 2333 c := ts.Client() 2334 2335 closes := 0 2336 2337 res, err := c.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")}) 2338 if err != nil { 2339 t.Fatal(err) 2340 } 2341 res.Body.Close() 2342 if closes != 1 { 2343 t.Errorf("closes = %d; want 1", closes) 2344 } 2345 } 2346 2347 func TestTransportTLSHandshakeTimeout(t *testing.T) { 2348 defer afterTest(t) 2349 if testing.Short() { 2350 t.Skip("skipping in short mode") 2351 } 2352 ln := newLocalListener(t) 2353 defer ln.Close() 2354 testdonec := make(chan struct{}) 2355 defer close(testdonec) 2356 2357 go func() { 2358 c, err := ln.Accept() 2359 if err != nil { 2360 t.Error(err) 2361 return 2362 } 2363 <-testdonec 2364 c.Close() 2365 }() 2366 2367 getdonec := make(chan struct{}) 2368 go func() { 2369 defer close(getdonec) 2370 tr := &Transport{ 2371 Dial: func(_, _ string) (net.Conn, error) { 2372 return net.Dial("tcp", ln.Addr().String()) 2373 }, 2374 TLSHandshakeTimeout: 250 * time.Millisecond, 2375 } 2376 cl := &Client{Transport: tr} 2377 _, err := cl.Get("https://dummy.tld/") 2378 if err == nil { 2379 t.Error("expected error") 2380 return 2381 } 2382 ue, ok := err.(*url.Error) 2383 if !ok { 2384 t.Errorf("expected url.Error; got %#v", err) 2385 return 2386 } 2387 ne, ok := ue.Err.(net.Error) 2388 if !ok { 2389 t.Errorf("expected net.Error; got %#v", err) 2390 return 2391 } 2392 if !ne.Timeout() { 2393 t.Errorf("expected timeout error; got %v", err) 2394 } 2395 if !strings.Contains(err.Error(), "handshake timeout") { 2396 t.Errorf("expected 'handshake timeout' in error; got %v", err) 2397 } 2398 }() 2399 select { 2400 case <-getdonec: 2401 case <-time.After(5 * time.Second): 2402 t.Error("test timeout; TLS handshake hung?") 2403 } 2404 } 2405 2406 // Trying to repro golang.org/issue/3514 2407 func TestTLSServerClosesConnection(t *testing.T) { 2408 defer afterTest(t) 2409 testenv.SkipFlaky(t, 7634) 2410 2411 closedc := make(chan bool, 1) 2412 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2413 if strings.Contains(r.URL.Path, "/keep-alive-then-die") { 2414 conn, _, _ := w.(Hijacker).Hijack() 2415 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) 2416 conn.Close() 2417 closedc <- true 2418 return 2419 } 2420 fmt.Fprintf(w, "hello") 2421 })) 2422 defer ts.Close() 2423 2424 c := ts.Client() 2425 tr := c.Transport.(*Transport) 2426 2427 var nSuccess = 0 2428 var errs []error 2429 const trials = 20 2430 for i := 0; i < trials; i++ { 2431 tr.CloseIdleConnections() 2432 res, err := c.Get(ts.URL + "/keep-alive-then-die") 2433 if err != nil { 2434 t.Fatal(err) 2435 } 2436 <-closedc 2437 slurp, err := ioutil.ReadAll(res.Body) 2438 if err != nil { 2439 t.Fatal(err) 2440 } 2441 if string(slurp) != "foo" { 2442 t.Errorf("Got %q, want foo", slurp) 2443 } 2444 2445 // Now try again and see if we successfully 2446 // pick a new connection. 2447 res, err = c.Get(ts.URL + "/") 2448 if err != nil { 2449 errs = append(errs, err) 2450 continue 2451 } 2452 slurp, err = ioutil.ReadAll(res.Body) 2453 if err != nil { 2454 errs = append(errs, err) 2455 continue 2456 } 2457 nSuccess++ 2458 } 2459 if nSuccess > 0 { 2460 t.Logf("successes = %d of %d", nSuccess, trials) 2461 } else { 2462 t.Errorf("All runs failed:") 2463 } 2464 for _, err := range errs { 2465 t.Logf(" err: %v", err) 2466 } 2467 } 2468 2469 // byteFromChanReader is an io.Reader that reads a single byte at a 2470 // time from the channel. When the channel is closed, the reader 2471 // returns io.EOF. 2472 type byteFromChanReader chan byte 2473 2474 func (c byteFromChanReader) Read(p []byte) (n int, err error) { 2475 if len(p) == 0 { 2476 return 2477 } 2478 b, ok := <-c 2479 if !ok { 2480 return 0, io.EOF 2481 } 2482 p[0] = b 2483 return 1, nil 2484 } 2485 2486 // Verifies that the Transport doesn't reuse a connection in the case 2487 // where the server replies before the request has been fully 2488 // written. We still honor that reply (see TestIssue3595), but don't 2489 // send future requests on the connection because it's then in a 2490 // questionable state. 2491 // golang.org/issue/7569 2492 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) { 2493 setParallel(t) 2494 defer afterTest(t) 2495 var sconn struct { 2496 sync.Mutex 2497 c net.Conn 2498 } 2499 var getOkay bool 2500 closeConn := func() { 2501 sconn.Lock() 2502 defer sconn.Unlock() 2503 if sconn.c != nil { 2504 sconn.c.Close() 2505 sconn.c = nil 2506 if !getOkay { 2507 t.Logf("Closed server connection") 2508 } 2509 } 2510 } 2511 defer closeConn() 2512 2513 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2514 if r.Method == "GET" { 2515 io.WriteString(w, "bar") 2516 return 2517 } 2518 conn, _, _ := w.(Hijacker).Hijack() 2519 sconn.Lock() 2520 sconn.c = conn 2521 sconn.Unlock() 2522 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive 2523 go io.Copy(ioutil.Discard, conn) 2524 })) 2525 defer ts.Close() 2526 c := ts.Client() 2527 2528 const bodySize = 256 << 10 2529 finalBit := make(byteFromChanReader, 1) 2530 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit)) 2531 req.ContentLength = bodySize 2532 res, err := c.Do(req) 2533 if err := wantBody(res, err, "foo"); err != nil { 2534 t.Errorf("POST response: %v", err) 2535 } 2536 donec := make(chan bool) 2537 go func() { 2538 defer close(donec) 2539 res, err = c.Get(ts.URL) 2540 if err := wantBody(res, err, "bar"); err != nil { 2541 t.Errorf("GET response: %v", err) 2542 return 2543 } 2544 getOkay = true // suppress test noise 2545 }() 2546 time.AfterFunc(5*time.Second, closeConn) 2547 select { 2548 case <-donec: 2549 finalBit <- 'x' // unblock the writeloop of the first Post 2550 close(finalBit) 2551 case <-time.After(7 * time.Second): 2552 t.Fatal("timeout waiting for GET request to finish") 2553 } 2554 } 2555 2556 // Tests that we don't leak Transport persistConn.readLoop goroutines 2557 // when a server hangs up immediately after saying it would keep-alive. 2558 func TestTransportIssue10457(t *testing.T) { 2559 defer afterTest(t) // used to fail in goroutine leak check 2560 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2561 // Send a response with no body, keep-alive 2562 // (implicit), and then lie and immediately close the 2563 // connection. This forces the Transport's readLoop to 2564 // immediately Peek an io.EOF and get to the point 2565 // that used to hang. 2566 conn, _, _ := w.(Hijacker).Hijack() 2567 conn.Write([]byte("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 0\r\n\r\n")) // keep-alive 2568 conn.Close() 2569 })) 2570 defer ts.Close() 2571 c := ts.Client() 2572 2573 res, err := c.Get(ts.URL) 2574 if err != nil { 2575 t.Fatalf("Get: %v", err) 2576 } 2577 defer res.Body.Close() 2578 2579 // Just a sanity check that we at least get the response. The real 2580 // test here is that the "defer afterTest" above doesn't find any 2581 // leaked goroutines. 2582 if got, want := res.Header.Get("Foo"), "Bar"; got != want { 2583 t.Errorf("Foo header = %q; want %q", got, want) 2584 } 2585 } 2586 2587 type errorReader struct { 2588 err error 2589 } 2590 2591 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err } 2592 2593 type closerFunc func() error 2594 2595 func (f closerFunc) Close() error { return f() } 2596 2597 type writerFuncConn struct { 2598 net.Conn 2599 write func(p []byte) (n int, err error) 2600 } 2601 2602 func (c writerFuncConn) Write(p []byte) (n int, err error) { return c.write(p) } 2603 2604 // Issues 4677, 18241, and 17844. If we try to reuse a connection that the 2605 // server is in the process of closing, we may end up successfully writing out 2606 // our request (or a portion of our request) only to find a connection error 2607 // when we try to read from (or finish writing to) the socket. 2608 // 2609 // NOTE: we resend a request only if: 2610 // - we reused a keep-alive connection 2611 // - we haven't yet received any header data 2612 // - either we wrote no bytes to the server, or the request is idempotent 2613 // This automatically prevents an infinite resend loop because we'll run out of 2614 // the cached keep-alive connections eventually. 2615 func TestRetryRequestsOnError(t *testing.T) { 2616 newRequest := func(method, urlStr string, body io.Reader) *Request { 2617 req, err := NewRequest(method, urlStr, body) 2618 if err != nil { 2619 t.Fatal(err) 2620 } 2621 return req 2622 } 2623 2624 testCases := []struct { 2625 name string 2626 failureN int 2627 failureErr error 2628 // Note that we can't just re-use the Request object across calls to c.Do 2629 // because we need to rewind Body between calls. (GetBody is only used to 2630 // rewind Body on failure and redirects, not just because it's done.) 2631 req func() *Request 2632 reqString string 2633 }{ 2634 { 2635 name: "IdempotentNoBodySomeWritten", 2636 // Believe that we've written some bytes to the server, so we know we're 2637 // not just in the "retry when no bytes sent" case". 2638 failureN: 1, 2639 // Use the specific error that shouldRetryRequest looks for with idempotent requests. 2640 failureErr: ExportErrServerClosedIdle, 2641 req: func() *Request { 2642 return newRequest("GET", "http://fake.golang", nil) 2643 }, 2644 reqString: `GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n`, 2645 }, 2646 { 2647 name: "IdempotentGetBodySomeWritten", 2648 // Believe that we've written some bytes to the server, so we know we're 2649 // not just in the "retry when no bytes sent" case". 2650 failureN: 1, 2651 // Use the specific error that shouldRetryRequest looks for with idempotent requests. 2652 failureErr: ExportErrServerClosedIdle, 2653 req: func() *Request { 2654 return newRequest("GET", "http://fake.golang", strings.NewReader("foo\n")) 2655 }, 2656 reqString: `GET / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 4\r\nAccept-Encoding: gzip\r\n\r\nfoo\n`, 2657 }, 2658 { 2659 name: "NothingWrittenNoBody", 2660 // It's key that we return 0 here -- that's what enables Transport to know 2661 // that nothing was written, even though this is a non-idempotent request. 2662 failureN: 0, 2663 failureErr: errors.New("second write fails"), 2664 req: func() *Request { 2665 return newRequest("DELETE", "http://fake.golang", nil) 2666 }, 2667 reqString: `DELETE / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nAccept-Encoding: gzip\r\n\r\n`, 2668 }, 2669 { 2670 name: "NothingWrittenGetBody", 2671 // It's key that we return 0 here -- that's what enables Transport to know 2672 // that nothing was written, even though this is a non-idempotent request. 2673 failureN: 0, 2674 failureErr: errors.New("second write fails"), 2675 // Note that NewRequest will set up GetBody for strings.Reader, which is 2676 // required for the retry to occur 2677 req: func() *Request { 2678 return newRequest("POST", "http://fake.golang", strings.NewReader("foo\n")) 2679 }, 2680 reqString: `POST / HTTP/1.1\r\nHost: fake.golang\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 4\r\nAccept-Encoding: gzip\r\n\r\nfoo\n`, 2681 }, 2682 } 2683 2684 for _, tc := range testCases { 2685 t.Run(tc.name, func(t *testing.T) { 2686 defer afterTest(t) 2687 2688 var ( 2689 mu sync.Mutex 2690 logbuf bytes.Buffer 2691 ) 2692 logf := func(format string, args ...interface{}) { 2693 mu.Lock() 2694 defer mu.Unlock() 2695 fmt.Fprintf(&logbuf, format, args...) 2696 logbuf.WriteByte('\n') 2697 } 2698 2699 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2700 logf("Handler") 2701 w.Header().Set("X-Status", "ok") 2702 })) 2703 defer ts.Close() 2704 2705 var writeNumAtomic int32 2706 c := ts.Client() 2707 c.Transport.(*Transport).Dial = func(network, addr string) (net.Conn, error) { 2708 logf("Dial") 2709 c, err := net.Dial(network, ts.Listener.Addr().String()) 2710 if err != nil { 2711 logf("Dial error: %v", err) 2712 return nil, err 2713 } 2714 return &writerFuncConn{ 2715 Conn: c, 2716 write: func(p []byte) (n int, err error) { 2717 if atomic.AddInt32(&writeNumAtomic, 1) == 2 { 2718 logf("intentional write failure") 2719 return tc.failureN, tc.failureErr 2720 } 2721 logf("Write(%q)", p) 2722 return c.Write(p) 2723 }, 2724 }, nil 2725 } 2726 2727 SetRoundTripRetried(func() { 2728 logf("Retried.") 2729 }) 2730 defer SetRoundTripRetried(nil) 2731 2732 for i := 0; i < 3; i++ { 2733 res, err := c.Do(tc.req()) 2734 if err != nil { 2735 t.Fatalf("i=%d: Do = %v", i, err) 2736 } 2737 res.Body.Close() 2738 } 2739 2740 mu.Lock() 2741 got := logbuf.String() 2742 mu.Unlock() 2743 want := fmt.Sprintf(`Dial 2744 Write("%s") 2745 Handler 2746 intentional write failure 2747 Retried. 2748 Dial 2749 Write("%s") 2750 Handler 2751 Write("%s") 2752 Handler 2753 `, tc.reqString, tc.reqString, tc.reqString) 2754 if got != want { 2755 t.Errorf("Log of events differs. Got:\n%s\nWant:\n%s", got, want) 2756 } 2757 }) 2758 } 2759 } 2760 2761 // Issue 6981 2762 func TestTransportClosesBodyOnError(t *testing.T) { 2763 setParallel(t) 2764 defer afterTest(t) 2765 readBody := make(chan error, 1) 2766 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2767 _, err := ioutil.ReadAll(r.Body) 2768 readBody <- err 2769 })) 2770 defer ts.Close() 2771 c := ts.Client() 2772 fakeErr := errors.New("fake error") 2773 didClose := make(chan bool, 1) 2774 req, _ := NewRequest("POST", ts.URL, struct { 2775 io.Reader 2776 io.Closer 2777 }{ 2778 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}), 2779 closerFunc(func() error { 2780 select { 2781 case didClose <- true: 2782 default: 2783 } 2784 return nil 2785 }), 2786 }) 2787 res, err := c.Do(req) 2788 if res != nil { 2789 defer res.Body.Close() 2790 } 2791 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 2792 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 2793 } 2794 select { 2795 case err := <-readBody: 2796 if err == nil { 2797 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 2798 } 2799 case <-time.After(5 * time.Second): 2800 t.Error("timeout waiting for server handler to complete") 2801 } 2802 select { 2803 case <-didClose: 2804 default: 2805 t.Errorf("didn't see Body.Close") 2806 } 2807 } 2808 2809 func TestTransportDialTLS(t *testing.T) { 2810 setParallel(t) 2811 defer afterTest(t) 2812 var mu sync.Mutex // guards following 2813 var gotReq, didDial bool 2814 2815 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2816 mu.Lock() 2817 gotReq = true 2818 mu.Unlock() 2819 })) 2820 defer ts.Close() 2821 c := ts.Client() 2822 c.Transport.(*Transport).DialTLS = func(netw, addr string) (net.Conn, error) { 2823 mu.Lock() 2824 didDial = true 2825 mu.Unlock() 2826 c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig) 2827 if err != nil { 2828 return nil, err 2829 } 2830 return c, c.Handshake() 2831 } 2832 2833 res, err := c.Get(ts.URL) 2834 if err != nil { 2835 t.Fatal(err) 2836 } 2837 res.Body.Close() 2838 mu.Lock() 2839 if !gotReq { 2840 t.Error("didn't get request") 2841 } 2842 if !didDial { 2843 t.Error("didn't use dial hook") 2844 } 2845 } 2846 2847 // Test for issue 8755 2848 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 2849 func TestRoundTripReturnsProxyError(t *testing.T) { 2850 badProxy := func(*Request) (*url.URL, error) { 2851 return nil, errors.New("errorMessage") 2852 } 2853 2854 tr := &Transport{Proxy: badProxy} 2855 2856 req, _ := NewRequest("GET", "http://example.com", nil) 2857 2858 _, err := tr.RoundTrip(req) 2859 2860 if err == nil { 2861 t.Error("Expected proxy error to be returned by RoundTrip") 2862 } 2863 } 2864 2865 // tests that putting an idle conn after a call to CloseIdleConns does return it 2866 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 2867 tr := &Transport{} 2868 wantIdle := func(when string, n int) bool { 2869 got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn 2870 if got == n { 2871 return true 2872 } 2873 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 2874 return false 2875 } 2876 wantIdle("start", 0) 2877 if !tr.PutIdleTestConn() { 2878 t.Fatal("put failed") 2879 } 2880 if !tr.PutIdleTestConn() { 2881 t.Fatal("second put failed") 2882 } 2883 wantIdle("after put", 2) 2884 tr.CloseIdleConnections() 2885 if !tr.IsIdleForTesting() { 2886 t.Error("should be idle after CloseIdleConnections") 2887 } 2888 wantIdle("after close idle", 0) 2889 if tr.PutIdleTestConn() { 2890 t.Fatal("put didn't fail") 2891 } 2892 wantIdle("after second put", 0) 2893 2894 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode 2895 if tr.IsIdleForTesting() { 2896 t.Error("shouldn't be idle after RequestIdleConnChForTesting") 2897 } 2898 if !tr.PutIdleTestConn() { 2899 t.Fatal("after re-activation") 2900 } 2901 wantIdle("after final put", 1) 2902 } 2903 2904 // This tests that an client requesting a content range won't also 2905 // implicitly ask for gzip support. If they want that, they need to do it 2906 // on their own. 2907 // golang.org/issue/8923 2908 func TestTransportRangeAndGzip(t *testing.T) { 2909 defer afterTest(t) 2910 reqc := make(chan *Request, 1) 2911 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2912 reqc <- r 2913 })) 2914 defer ts.Close() 2915 c := ts.Client() 2916 2917 req, _ := NewRequest("GET", ts.URL, nil) 2918 req.Header.Set("Range", "bytes=7-11") 2919 res, err := c.Do(req) 2920 if err != nil { 2921 t.Fatal(err) 2922 } 2923 2924 select { 2925 case r := <-reqc: 2926 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 2927 t.Error("Transport advertised gzip support in the Accept header") 2928 } 2929 if r.Header.Get("Range") == "" { 2930 t.Error("no Range in request") 2931 } 2932 case <-time.After(10 * time.Second): 2933 t.Fatal("timeout") 2934 } 2935 res.Body.Close() 2936 } 2937 2938 // Test for issue 10474 2939 func TestTransportResponseCancelRace(t *testing.T) { 2940 defer afterTest(t) 2941 2942 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2943 // important that this response has a body. 2944 var b [1024]byte 2945 w.Write(b[:]) 2946 })) 2947 defer ts.Close() 2948 tr := ts.Client().Transport.(*Transport) 2949 2950 req, err := NewRequest("GET", ts.URL, nil) 2951 if err != nil { 2952 t.Fatal(err) 2953 } 2954 res, err := tr.RoundTrip(req) 2955 if err != nil { 2956 t.Fatal(err) 2957 } 2958 // If we do an early close, Transport just throws the connection away and 2959 // doesn't reuse it. In order to trigger the bug, it has to reuse the connection 2960 // so read the body 2961 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { 2962 t.Fatal(err) 2963 } 2964 2965 req2, err := NewRequest("GET", ts.URL, nil) 2966 if err != nil { 2967 t.Fatal(err) 2968 } 2969 tr.CancelRequest(req) 2970 res, err = tr.RoundTrip(req2) 2971 if err != nil { 2972 t.Fatal(err) 2973 } 2974 res.Body.Close() 2975 } 2976 2977 // Test for issue 19248: Content-Encoding's value is case insensitive. 2978 func TestTransportContentEncodingCaseInsensitive(t *testing.T) { 2979 setParallel(t) 2980 defer afterTest(t) 2981 for _, ce := range []string{"gzip", "GZIP"} { 2982 ce := ce 2983 t.Run(ce, func(t *testing.T) { 2984 const encodedString = "Hello Gopher" 2985 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2986 w.Header().Set("Content-Encoding", ce) 2987 gz := gzip.NewWriter(w) 2988 gz.Write([]byte(encodedString)) 2989 gz.Close() 2990 })) 2991 defer ts.Close() 2992 2993 res, err := ts.Client().Get(ts.URL) 2994 if err != nil { 2995 t.Fatal(err) 2996 } 2997 2998 body, err := ioutil.ReadAll(res.Body) 2999 res.Body.Close() 3000 if err != nil { 3001 t.Fatal(err) 3002 } 3003 3004 if string(body) != encodedString { 3005 t.Fatalf("Expected body %q, got: %q\n", encodedString, string(body)) 3006 } 3007 }) 3008 } 3009 } 3010 3011 func TestTransportDialCancelRace(t *testing.T) { 3012 defer afterTest(t) 3013 3014 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 3015 defer ts.Close() 3016 tr := ts.Client().Transport.(*Transport) 3017 3018 req, err := NewRequest("GET", ts.URL, nil) 3019 if err != nil { 3020 t.Fatal(err) 3021 } 3022 SetEnterRoundTripHook(func() { 3023 tr.CancelRequest(req) 3024 }) 3025 defer SetEnterRoundTripHook(nil) 3026 res, err := tr.RoundTrip(req) 3027 if err != ExportErrRequestCanceled { 3028 t.Errorf("expected canceled request error; got %v", err) 3029 if err == nil { 3030 res.Body.Close() 3031 } 3032 } 3033 } 3034 3035 // logWritesConn is a net.Conn that logs each Write call to writes 3036 // and then proxies to w. 3037 // It proxies Read calls to a reader it receives from rch. 3038 type logWritesConn struct { 3039 net.Conn // nil. crash on use. 3040 3041 w io.Writer 3042 3043 rch <-chan io.Reader 3044 r io.Reader // nil until received by rch 3045 3046 mu sync.Mutex 3047 writes []string 3048 } 3049 3050 func (c *logWritesConn) Write(p []byte) (n int, err error) { 3051 c.mu.Lock() 3052 defer c.mu.Unlock() 3053 c.writes = append(c.writes, string(p)) 3054 return c.w.Write(p) 3055 } 3056 3057 func (c *logWritesConn) Read(p []byte) (n int, err error) { 3058 if c.r == nil { 3059 c.r = <-c.rch 3060 } 3061 return c.r.Read(p) 3062 } 3063 3064 func (c *logWritesConn) Close() error { return nil } 3065 3066 // Issue 6574 3067 func TestTransportFlushesBodyChunks(t *testing.T) { 3068 defer afterTest(t) 3069 resBody := make(chan io.Reader, 1) 3070 connr, connw := io.Pipe() // connection pipe pair 3071 lw := &logWritesConn{ 3072 rch: resBody, 3073 w: connw, 3074 } 3075 tr := &Transport{ 3076 Dial: func(network, addr string) (net.Conn, error) { 3077 return lw, nil 3078 }, 3079 } 3080 bodyr, bodyw := io.Pipe() // body pipe pair 3081 go func() { 3082 defer bodyw.Close() 3083 for i := 0; i < 3; i++ { 3084 fmt.Fprintf(bodyw, "num%d\n", i) 3085 } 3086 }() 3087 resc := make(chan *Response) 3088 go func() { 3089 req, _ := NewRequest("POST", "http://localhost:8080", bodyr) 3090 req.Header.Set("User-Agent", "x") // known value for test 3091 res, err := tr.RoundTrip(req) 3092 if err != nil { 3093 t.Errorf("RoundTrip: %v", err) 3094 close(resc) 3095 return 3096 } 3097 resc <- res 3098 3099 }() 3100 // Fully consume the request before checking the Write log vs. want. 3101 req, err := ReadRequest(bufio.NewReader(connr)) 3102 if err != nil { 3103 t.Fatal(err) 3104 } 3105 io.Copy(ioutil.Discard, req.Body) 3106 3107 // Unblock the transport's roundTrip goroutine. 3108 resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n") 3109 res, ok := <-resc 3110 if !ok { 3111 return 3112 } 3113 defer res.Body.Close() 3114 3115 want := []string{ 3116 "POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n" + 3117 "5\r\nnum0\n\r\n", 3118 "5\r\nnum1\n\r\n", 3119 "5\r\nnum2\n\r\n", 3120 "0\r\n\r\n", 3121 } 3122 if !reflect.DeepEqual(lw.writes, want) { 3123 t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want) 3124 } 3125 } 3126 3127 // Issue 11745. 3128 func TestTransportPrefersResponseOverWriteError(t *testing.T) { 3129 if testing.Short() { 3130 t.Skip("skipping in short mode") 3131 } 3132 defer afterTest(t) 3133 const contentLengthLimit = 1024 * 1024 // 1MB 3134 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3135 if r.ContentLength >= contentLengthLimit { 3136 w.WriteHeader(StatusBadRequest) 3137 r.Body.Close() 3138 return 3139 } 3140 w.WriteHeader(StatusOK) 3141 })) 3142 defer ts.Close() 3143 c := ts.Client() 3144 3145 fail := 0 3146 count := 100 3147 bigBody := strings.Repeat("a", contentLengthLimit*2) 3148 for i := 0; i < count; i++ { 3149 req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody)) 3150 if err != nil { 3151 t.Fatal(err) 3152 } 3153 resp, err := c.Do(req) 3154 if err != nil { 3155 fail++ 3156 t.Logf("%d = %#v", i, err) 3157 if ue, ok := err.(*url.Error); ok { 3158 t.Logf("urlErr = %#v", ue.Err) 3159 if ne, ok := ue.Err.(*net.OpError); ok { 3160 t.Logf("netOpError = %#v", ne.Err) 3161 } 3162 } 3163 } else { 3164 resp.Body.Close() 3165 if resp.StatusCode != 400 { 3166 t.Errorf("Expected status code 400, got %v", resp.Status) 3167 } 3168 } 3169 } 3170 if fail > 0 { 3171 t.Errorf("Failed %v out of %v\n", fail, count) 3172 } 3173 } 3174 3175 func TestTransportAutomaticHTTP2(t *testing.T) { 3176 testTransportAutoHTTP(t, &Transport{}, true) 3177 } 3178 3179 // golang.org/issue/14391: also check DefaultTransport 3180 func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) { 3181 testTransportAutoHTTP(t, DefaultTransport.(*Transport), true) 3182 } 3183 3184 func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { 3185 testTransportAutoHTTP(t, &Transport{ 3186 TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), 3187 }, false) 3188 } 3189 3190 func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { 3191 testTransportAutoHTTP(t, &Transport{ 3192 TLSClientConfig: new(tls.Config), 3193 }, false) 3194 } 3195 3196 func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { 3197 testTransportAutoHTTP(t, &Transport{ 3198 ExpectContinueTimeout: 1 * time.Second, 3199 }, true) 3200 } 3201 3202 func TestTransportAutomaticHTTP2_Dial(t *testing.T) { 3203 var d net.Dialer 3204 testTransportAutoHTTP(t, &Transport{ 3205 Dial: d.Dial, 3206 }, false) 3207 } 3208 3209 func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) { 3210 testTransportAutoHTTP(t, &Transport{ 3211 DialTLS: func(network, addr string) (net.Conn, error) { 3212 panic("unused") 3213 }, 3214 }, false) 3215 } 3216 3217 func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { 3218 _, err := tr.RoundTrip(new(Request)) 3219 if err == nil { 3220 t.Error("expected error from RoundTrip") 3221 } 3222 if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { 3223 t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) 3224 } 3225 } 3226 3227 // Issue 13633: there was a race where we returned bodyless responses 3228 // to callers before recycling the persistent connection, which meant 3229 // a client doing two subsequent requests could end up on different 3230 // connections. It's somewhat harmless but enough tests assume it's 3231 // not true in order to test other things that it's worth fixing. 3232 // Plus it's nice to be consistent and not have timing-dependent 3233 // behavior. 3234 func TestTransportReuseConnEmptyResponseBody(t *testing.T) { 3235 defer afterTest(t) 3236 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3237 w.Header().Set("X-Addr", r.RemoteAddr) 3238 // Empty response body. 3239 })) 3240 defer cst.close() 3241 n := 100 3242 if testing.Short() { 3243 n = 10 3244 } 3245 var firstAddr string 3246 for i := 0; i < n; i++ { 3247 res, err := cst.c.Get(cst.ts.URL) 3248 if err != nil { 3249 log.Fatal(err) 3250 } 3251 addr := res.Header.Get("X-Addr") 3252 if i == 0 { 3253 firstAddr = addr 3254 } else if addr != firstAddr { 3255 t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr) 3256 } 3257 res.Body.Close() 3258 } 3259 } 3260 3261 // Issue 13839 3262 func TestNoCrashReturningTransportAltConn(t *testing.T) { 3263 cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) 3264 if err != nil { 3265 t.Fatal(err) 3266 } 3267 ln := newLocalListener(t) 3268 defer ln.Close() 3269 3270 handledPendingDial := make(chan bool, 1) 3271 SetPendingDialHooks(nil, func() { handledPendingDial <- true }) 3272 defer SetPendingDialHooks(nil, nil) 3273 3274 testDone := make(chan struct{}) 3275 defer close(testDone) 3276 go func() { 3277 tln := tls.NewListener(ln, &tls.Config{ 3278 NextProtos: []string{"foo"}, 3279 Certificates: []tls.Certificate{cert}, 3280 }) 3281 sc, err := tln.Accept() 3282 if err != nil { 3283 t.Error(err) 3284 return 3285 } 3286 if err := sc.(*tls.Conn).Handshake(); err != nil { 3287 t.Error(err) 3288 return 3289 } 3290 <-testDone 3291 sc.Close() 3292 }() 3293 3294 addr := ln.Addr().String() 3295 3296 req, _ := NewRequest("GET", "https://fake.tld/", nil) 3297 cancel := make(chan struct{}) 3298 req.Cancel = cancel 3299 3300 doReturned := make(chan bool, 1) 3301 madeRoundTripper := make(chan bool, 1) 3302 3303 tr := &Transport{ 3304 DisableKeepAlives: true, 3305 TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{ 3306 "foo": func(authority string, c *tls.Conn) RoundTripper { 3307 madeRoundTripper <- true 3308 return funcRoundTripper(func() { 3309 t.Error("foo RoundTripper should not be called") 3310 }) 3311 }, 3312 }, 3313 Dial: func(_, _ string) (net.Conn, error) { 3314 panic("shouldn't be called") 3315 }, 3316 DialTLS: func(_, _ string) (net.Conn, error) { 3317 tc, err := tls.Dial("tcp", addr, &tls.Config{ 3318 InsecureSkipVerify: true, 3319 NextProtos: []string{"foo"}, 3320 }) 3321 if err != nil { 3322 return nil, err 3323 } 3324 if err := tc.Handshake(); err != nil { 3325 return nil, err 3326 } 3327 close(cancel) 3328 <-doReturned 3329 return tc, nil 3330 }, 3331 } 3332 c := &Client{Transport: tr} 3333 3334 _, err = c.Do(req) 3335 if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn { 3336 t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err) 3337 } 3338 3339 doReturned <- true 3340 <-madeRoundTripper 3341 <-handledPendingDial 3342 } 3343 3344 func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) { 3345 testTransportReuseConnection_Gzip(t, true) 3346 } 3347 3348 func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) { 3349 testTransportReuseConnection_Gzip(t, false) 3350 } 3351 3352 // Make sure we re-use underlying TCP connection for gzipped responses too. 3353 func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) { 3354 setParallel(t) 3355 defer afterTest(t) 3356 addr := make(chan string, 2) 3357 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3358 addr <- r.RemoteAddr 3359 w.Header().Set("Content-Encoding", "gzip") 3360 if chunked { 3361 w.(Flusher).Flush() 3362 } 3363 w.Write(rgz) // arbitrary gzip response 3364 })) 3365 defer ts.Close() 3366 c := ts.Client() 3367 3368 for i := 0; i < 2; i++ { 3369 res, err := c.Get(ts.URL) 3370 if err != nil { 3371 t.Fatal(err) 3372 } 3373 buf := make([]byte, len(rgz)) 3374 if n, err := io.ReadFull(res.Body, buf); err != nil { 3375 t.Errorf("%d. ReadFull = %v, %v", i, n, err) 3376 } 3377 // Note: no res.Body.Close call. It should work without it, 3378 // since the flate.Reader's internal buffering will hit EOF 3379 // and that should be sufficient. 3380 } 3381 a1, a2 := <-addr, <-addr 3382 if a1 != a2 { 3383 t.Fatalf("didn't reuse connection") 3384 } 3385 } 3386 3387 func TestTransportResponseHeaderLength(t *testing.T) { 3388 setParallel(t) 3389 defer afterTest(t) 3390 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3391 if r.URL.Path == "/long" { 3392 w.Header().Set("Long", strings.Repeat("a", 1<<20)) 3393 } 3394 })) 3395 defer ts.Close() 3396 c := ts.Client() 3397 c.Transport.(*Transport).MaxResponseHeaderBytes = 512 << 10 3398 3399 if res, err := c.Get(ts.URL); err != nil { 3400 t.Fatal(err) 3401 } else { 3402 res.Body.Close() 3403 } 3404 3405 res, err := c.Get(ts.URL + "/long") 3406 if err == nil { 3407 defer res.Body.Close() 3408 var n int64 3409 for k, vv := range res.Header { 3410 for _, v := range vv { 3411 n += int64(len(k)) + int64(len(v)) 3412 } 3413 } 3414 t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n) 3415 } 3416 if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) { 3417 t.Errorf("got error: %v; want %q", err, want) 3418 } 3419 } 3420 3421 func TestTransportEventTrace(t *testing.T) { testTransportEventTrace(t, h1Mode, false) } 3422 func TestTransportEventTrace_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, false) } 3423 3424 // test a non-nil httptrace.ClientTrace but with all hooks set to zero. 3425 func TestTransportEventTrace_NoHooks(t *testing.T) { testTransportEventTrace(t, h1Mode, true) } 3426 func TestTransportEventTrace_NoHooks_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, true) } 3427 3428 func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { 3429 defer afterTest(t) 3430 const resBody = "some body" 3431 gotWroteReqEvent := make(chan struct{}) 3432 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3433 if _, err := ioutil.ReadAll(r.Body); err != nil { 3434 t.Error(err) 3435 } 3436 if !noHooks { 3437 select { 3438 case <-gotWroteReqEvent: 3439 case <-time.After(5 * time.Second): 3440 t.Error("timeout waiting for WroteRequest event") 3441 } 3442 } 3443 io.WriteString(w, resBody) 3444 })) 3445 defer cst.close() 3446 3447 cst.tr.ExpectContinueTimeout = 1 * time.Second 3448 3449 var mu sync.Mutex // guards buf 3450 var buf bytes.Buffer 3451 logf := func(format string, args ...interface{}) { 3452 mu.Lock() 3453 defer mu.Unlock() 3454 fmt.Fprintf(&buf, format, args...) 3455 buf.WriteByte('\n') 3456 } 3457 3458 addrStr := cst.ts.Listener.Addr().String() 3459 ip, port, err := net.SplitHostPort(addrStr) 3460 if err != nil { 3461 t.Fatal(err) 3462 } 3463 3464 // Install a fake DNS server. 3465 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3466 if host != "dns-is-faked.golang" { 3467 t.Errorf("unexpected DNS host lookup for %q", host) 3468 return nil, nil 3469 } 3470 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3471 }) 3472 3473 req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader("some body")) 3474 trace := &httptrace.ClientTrace{ 3475 GetConn: func(hostPort string) { logf("Getting conn for %v ...", hostPort) }, 3476 GotConn: func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) }, 3477 GotFirstResponseByte: func() { logf("first response byte") }, 3478 PutIdleConn: func(err error) { logf("PutIdleConn = %v", err) }, 3479 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) }, 3480 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) }, 3481 ConnectStart: func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) }, 3482 ConnectDone: func(network, addr string, err error) { 3483 if err != nil { 3484 t.Errorf("ConnectDone: %v", err) 3485 } 3486 logf("ConnectDone: connected to %s %s = %v", network, addr, err) 3487 }, 3488 Wait100Continue: func() { logf("Wait100Continue") }, 3489 Got100Continue: func() { logf("Got100Continue") }, 3490 WroteRequest: func(e httptrace.WroteRequestInfo) { 3491 logf("WroteRequest: %+v", e) 3492 close(gotWroteReqEvent) 3493 }, 3494 } 3495 if h2 { 3496 trace.TLSHandshakeStart = func() { logf("tls handshake start") } 3497 trace.TLSHandshakeDone = func(s tls.ConnectionState, err error) { 3498 logf("tls handshake done. ConnectionState = %v \n err = %v", s, err) 3499 } 3500 } 3501 if noHooks { 3502 // zero out all func pointers, trying to get some path to crash 3503 *trace = httptrace.ClientTrace{} 3504 } 3505 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 3506 3507 req.Header.Set("Expect", "100-continue") 3508 res, err := cst.c.Do(req) 3509 if err != nil { 3510 t.Fatal(err) 3511 } 3512 logf("got roundtrip.response") 3513 slurp, err := ioutil.ReadAll(res.Body) 3514 if err != nil { 3515 t.Fatal(err) 3516 } 3517 logf("consumed body") 3518 if string(slurp) != resBody || res.StatusCode != 200 { 3519 t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody) 3520 } 3521 res.Body.Close() 3522 3523 if noHooks { 3524 // Done at this point. Just testing a full HTTP 3525 // requests can happen with a trace pointing to a zero 3526 // ClientTrace, full of nil func pointers. 3527 return 3528 } 3529 3530 mu.Lock() 3531 got := buf.String() 3532 mu.Unlock() 3533 3534 wantOnce := func(sub string) { 3535 if strings.Count(got, sub) != 1 { 3536 t.Errorf("expected substring %q exactly once in output.", sub) 3537 } 3538 } 3539 wantOnceOrMore := func(sub string) { 3540 if strings.Count(got, sub) == 0 { 3541 t.Errorf("expected substring %q at least once in output.", sub) 3542 } 3543 } 3544 wantOnce("Getting conn for dns-is-faked.golang:" + port) 3545 wantOnce("DNS start: {Host:dns-is-faked.golang}") 3546 wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}") 3547 wantOnce("got conn: {") 3548 wantOnceOrMore("Connecting to tcp " + addrStr) 3549 wantOnceOrMore("connected to tcp " + addrStr + " = <nil>") 3550 wantOnce("Reused:false WasIdle:false IdleTime:0s") 3551 wantOnce("first response byte") 3552 if h2 { 3553 wantOnce("tls handshake start") 3554 wantOnce("tls handshake done") 3555 } else { 3556 wantOnce("PutIdleConn = <nil>") 3557 } 3558 wantOnce("Wait100Continue") 3559 wantOnce("Got100Continue") 3560 wantOnce("WroteRequest: {Err:<nil>}") 3561 if strings.Contains(got, " to udp ") { 3562 t.Errorf("should not see UDP (DNS) connections") 3563 } 3564 if t.Failed() { 3565 t.Errorf("Output:\n%s", got) 3566 } 3567 } 3568 3569 var ( 3570 isDNSHijackedOnce sync.Once 3571 isDNSHijacked bool 3572 ) 3573 3574 func skipIfDNSHijacked(t *testing.T) { 3575 // Skip this test if the user is using a shady/ISP 3576 // DNS server hijacking queries. 3577 // See issues 16732, 16716. 3578 isDNSHijackedOnce.Do(func() { 3579 addrs, _ := net.LookupHost("dns-should-not-resolve.golang") 3580 isDNSHijacked = len(addrs) != 0 3581 }) 3582 if isDNSHijacked { 3583 t.Skip("skipping; test requires non-hijacking DNS server") 3584 } 3585 } 3586 3587 func TestTransportEventTraceRealDNS(t *testing.T) { 3588 skipIfDNSHijacked(t) 3589 defer afterTest(t) 3590 tr := &Transport{} 3591 defer tr.CloseIdleConnections() 3592 c := &Client{Transport: tr} 3593 3594 var mu sync.Mutex // guards buf 3595 var buf bytes.Buffer 3596 logf := func(format string, args ...interface{}) { 3597 mu.Lock() 3598 defer mu.Unlock() 3599 fmt.Fprintf(&buf, format, args...) 3600 buf.WriteByte('\n') 3601 } 3602 3603 req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil) 3604 trace := &httptrace.ClientTrace{ 3605 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) }, 3606 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) }, 3607 ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) }, 3608 ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) }, 3609 } 3610 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 3611 3612 resp, err := c.Do(req) 3613 if err == nil { 3614 resp.Body.Close() 3615 t.Fatal("expected error during DNS lookup") 3616 } 3617 3618 mu.Lock() 3619 got := buf.String() 3620 mu.Unlock() 3621 3622 wantSub := func(sub string) { 3623 if !strings.Contains(got, sub) { 3624 t.Errorf("expected substring %q in output.", sub) 3625 } 3626 } 3627 wantSub("DNSStart: {Host:dns-should-not-resolve.golang}") 3628 wantSub("DNSDone: {Addrs:[] Err:") 3629 if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") { 3630 t.Errorf("should not see Connect events") 3631 } 3632 if t.Failed() { 3633 t.Errorf("Output:\n%s", got) 3634 } 3635 } 3636 3637 // Issue 14353: port can only contain digits. 3638 func TestTransportRejectsAlphaPort(t *testing.T) { 3639 res, err := Get("http://dummy.tld:123foo/bar") 3640 if err == nil { 3641 res.Body.Close() 3642 t.Fatal("unexpected success") 3643 } 3644 ue, ok := err.(*url.Error) 3645 if !ok { 3646 t.Fatalf("got %#v; want *url.Error", err) 3647 } 3648 got := ue.Err.Error() 3649 want := `invalid URL port "123foo"` 3650 if got != want { 3651 t.Errorf("got error %q; want %q", got, want) 3652 } 3653 } 3654 3655 // Test the httptrace.TLSHandshake{Start,Done} hooks with a https http1 3656 // connections. The http2 test is done in TestTransportEventTrace_h2 3657 func TestTLSHandshakeTrace(t *testing.T) { 3658 defer afterTest(t) 3659 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 3660 defer ts.Close() 3661 3662 var mu sync.Mutex 3663 var start, done bool 3664 trace := &httptrace.ClientTrace{ 3665 TLSHandshakeStart: func() { 3666 mu.Lock() 3667 defer mu.Unlock() 3668 start = true 3669 }, 3670 TLSHandshakeDone: func(s tls.ConnectionState, err error) { 3671 mu.Lock() 3672 defer mu.Unlock() 3673 done = true 3674 if err != nil { 3675 t.Fatal("Expected error to be nil but was:", err) 3676 } 3677 }, 3678 } 3679 3680 c := ts.Client() 3681 req, err := NewRequest("GET", ts.URL, nil) 3682 if err != nil { 3683 t.Fatal("Unable to construct test request:", err) 3684 } 3685 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) 3686 3687 r, err := c.Do(req) 3688 if err != nil { 3689 t.Fatal("Unexpected error making request:", err) 3690 } 3691 r.Body.Close() 3692 mu.Lock() 3693 defer mu.Unlock() 3694 if !start { 3695 t.Fatal("Expected TLSHandshakeStart to be called, but wasn't") 3696 } 3697 if !done { 3698 t.Fatal("Expected TLSHandshakeDone to be called, but wasnt't") 3699 } 3700 } 3701 3702 func TestTransportMaxIdleConns(t *testing.T) { 3703 defer afterTest(t) 3704 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3705 // No body for convenience. 3706 })) 3707 defer ts.Close() 3708 c := ts.Client() 3709 tr := c.Transport.(*Transport) 3710 tr.MaxIdleConns = 4 3711 3712 ip, port, err := net.SplitHostPort(ts.Listener.Addr().String()) 3713 if err != nil { 3714 t.Fatal(err) 3715 } 3716 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3717 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3718 }) 3719 3720 hitHost := func(n int) { 3721 req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil) 3722 req = req.WithContext(ctx) 3723 res, err := c.Do(req) 3724 if err != nil { 3725 t.Fatal(err) 3726 } 3727 res.Body.Close() 3728 } 3729 for i := 0; i < 4; i++ { 3730 hitHost(i) 3731 } 3732 want := []string{ 3733 "|http|host-0.dns-is-faked.golang:" + port, 3734 "|http|host-1.dns-is-faked.golang:" + port, 3735 "|http|host-2.dns-is-faked.golang:" + port, 3736 "|http|host-3.dns-is-faked.golang:" + port, 3737 } 3738 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3739 t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want) 3740 } 3741 3742 // Now hitting the 5th host should kick out the first host: 3743 hitHost(4) 3744 want = []string{ 3745 "|http|host-1.dns-is-faked.golang:" + port, 3746 "|http|host-2.dns-is-faked.golang:" + port, 3747 "|http|host-3.dns-is-faked.golang:" + port, 3748 "|http|host-4.dns-is-faked.golang:" + port, 3749 } 3750 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3751 t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want) 3752 } 3753 } 3754 3755 func TestTransportIdleConnTimeout_h1(t *testing.T) { testTransportIdleConnTimeout(t, h1Mode) } 3756 func TestTransportIdleConnTimeout_h2(t *testing.T) { testTransportIdleConnTimeout(t, h2Mode) } 3757 func testTransportIdleConnTimeout(t *testing.T, h2 bool) { 3758 if testing.Short() { 3759 t.Skip("skipping in short mode") 3760 } 3761 defer afterTest(t) 3762 3763 const timeout = 1 * time.Second 3764 3765 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3766 // No body for convenience. 3767 })) 3768 defer cst.close() 3769 tr := cst.tr 3770 tr.IdleConnTimeout = timeout 3771 defer tr.CloseIdleConnections() 3772 c := &Client{Transport: tr} 3773 3774 idleConns := func() []string { 3775 if h2 { 3776 return tr.IdleConnStrsForTesting_h2() 3777 } else { 3778 return tr.IdleConnStrsForTesting() 3779 } 3780 } 3781 3782 var conn string 3783 doReq := func(n int) { 3784 req, _ := NewRequest("GET", cst.ts.URL, nil) 3785 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 3786 PutIdleConn: func(err error) { 3787 if err != nil { 3788 t.Errorf("failed to keep idle conn: %v", err) 3789 } 3790 }, 3791 })) 3792 res, err := c.Do(req) 3793 if err != nil { 3794 t.Fatal(err) 3795 } 3796 res.Body.Close() 3797 conns := idleConns() 3798 if len(conns) != 1 { 3799 t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns) 3800 } 3801 if conn == "" { 3802 conn = conns[0] 3803 } 3804 if conn != conns[0] { 3805 t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n) 3806 } 3807 } 3808 for i := 0; i < 3; i++ { 3809 doReq(i) 3810 time.Sleep(timeout / 2) 3811 } 3812 time.Sleep(timeout * 3 / 2) 3813 if got := idleConns(); len(got) != 0 { 3814 t.Errorf("idle conns = %q; want none", got) 3815 } 3816 } 3817 3818 // Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an 3819 // HTTP/2 connection was established but but its caller no longer 3820 // wanted it. (Assuming the connection cache was enabled, which it is 3821 // by default) 3822 // 3823 // This test reproduced the crash by setting the IdleConnTimeout low 3824 // (to make the test reasonable) and then making a request which is 3825 // canceled by the DialTLS hook, which then also waits to return the 3826 // real connection until after the RoundTrip saw the error. Then we 3827 // know the successful tls.Dial from DialTLS will need to go into the 3828 // idle pool. Then we give it a of time to explode. 3829 func TestIdleConnH2Crash(t *testing.T) { 3830 setParallel(t) 3831 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3832 // nothing 3833 })) 3834 defer cst.close() 3835 3836 ctx, cancel := context.WithCancel(context.Background()) 3837 defer cancel() 3838 3839 sawDoErr := make(chan bool, 1) 3840 testDone := make(chan struct{}) 3841 defer close(testDone) 3842 3843 cst.tr.IdleConnTimeout = 5 * time.Millisecond 3844 cst.tr.DialTLS = func(network, addr string) (net.Conn, error) { 3845 c, err := tls.Dial(network, addr, &tls.Config{ 3846 InsecureSkipVerify: true, 3847 NextProtos: []string{"h2"}, 3848 }) 3849 if err != nil { 3850 t.Error(err) 3851 return nil, err 3852 } 3853 if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" { 3854 t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2") 3855 c.Close() 3856 return nil, errors.New("bogus") 3857 } 3858 3859 cancel() 3860 3861 failTimer := time.NewTimer(5 * time.Second) 3862 defer failTimer.Stop() 3863 select { 3864 case <-sawDoErr: 3865 case <-testDone: 3866 case <-failTimer.C: 3867 t.Error("timeout in DialTLS, waiting too long for cst.c.Do to fail") 3868 } 3869 return c, nil 3870 } 3871 3872 req, _ := NewRequest("GET", cst.ts.URL, nil) 3873 req = req.WithContext(ctx) 3874 res, err := cst.c.Do(req) 3875 if err == nil { 3876 res.Body.Close() 3877 t.Fatal("unexpected success") 3878 } 3879 sawDoErr <- true 3880 3881 // Wait for the explosion. 3882 time.Sleep(cst.tr.IdleConnTimeout * 10) 3883 } 3884 3885 type funcConn struct { 3886 net.Conn 3887 read func([]byte) (int, error) 3888 write func([]byte) (int, error) 3889 } 3890 3891 func (c funcConn) Read(p []byte) (int, error) { return c.read(p) } 3892 func (c funcConn) Write(p []byte) (int, error) { return c.write(p) } 3893 func (c funcConn) Close() error { return nil } 3894 3895 // Issue 16465: Transport.RoundTrip should return the raw net.Conn.Read error from Peek 3896 // back to the caller. 3897 func TestTransportReturnsPeekError(t *testing.T) { 3898 errValue := errors.New("specific error value") 3899 3900 wrote := make(chan struct{}) 3901 var wroteOnce sync.Once 3902 3903 tr := &Transport{ 3904 Dial: func(network, addr string) (net.Conn, error) { 3905 c := funcConn{ 3906 read: func([]byte) (int, error) { 3907 <-wrote 3908 return 0, errValue 3909 }, 3910 write: func(p []byte) (int, error) { 3911 wroteOnce.Do(func() { close(wrote) }) 3912 return len(p), nil 3913 }, 3914 } 3915 return c, nil 3916 }, 3917 } 3918 _, err := tr.RoundTrip(httptest.NewRequest("GET", "http://fake.tld/", nil)) 3919 if err != errValue { 3920 t.Errorf("error = %#v; want %v", err, errValue) 3921 } 3922 } 3923 3924 // Issue 13835: international domain names should work 3925 func TestTransportIDNA_h1(t *testing.T) { testTransportIDNA(t, h1Mode) } 3926 func TestTransportIDNA_h2(t *testing.T) { testTransportIDNA(t, h2Mode) } 3927 func testTransportIDNA(t *testing.T, h2 bool) { 3928 defer afterTest(t) 3929 3930 const uniDomain = "гофер.го" 3931 const punyDomain = "xn--c1ae0ajs.xn--c1aw" 3932 3933 var port string 3934 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3935 want := punyDomain + ":" + port 3936 if r.Host != want { 3937 t.Errorf("Host header = %q; want %q", r.Host, want) 3938 } 3939 if h2 { 3940 if r.TLS == nil { 3941 t.Errorf("r.TLS == nil") 3942 } else if r.TLS.ServerName != punyDomain { 3943 t.Errorf("TLS.ServerName = %q; want %q", r.TLS.ServerName, punyDomain) 3944 } 3945 } 3946 w.Header().Set("Hit-Handler", "1") 3947 })) 3948 defer cst.close() 3949 3950 ip, port, err := net.SplitHostPort(cst.ts.Listener.Addr().String()) 3951 if err != nil { 3952 t.Fatal(err) 3953 } 3954 3955 // Install a fake DNS server. 3956 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3957 if host != punyDomain { 3958 t.Errorf("got DNS host lookup for %q; want %q", host, punyDomain) 3959 return nil, nil 3960 } 3961 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3962 }) 3963 3964 req, _ := NewRequest("GET", cst.scheme()+"://"+uniDomain+":"+port, nil) 3965 trace := &httptrace.ClientTrace{ 3966 GetConn: func(hostPort string) { 3967 want := net.JoinHostPort(punyDomain, port) 3968 if hostPort != want { 3969 t.Errorf("getting conn for %q; want %q", hostPort, want) 3970 } 3971 }, 3972 DNSStart: func(e httptrace.DNSStartInfo) { 3973 if e.Host != punyDomain { 3974 t.Errorf("DNSStart Host = %q; want %q", e.Host, punyDomain) 3975 } 3976 }, 3977 } 3978 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 3979 3980 res, err := cst.tr.RoundTrip(req) 3981 if err != nil { 3982 t.Fatal(err) 3983 } 3984 defer res.Body.Close() 3985 if res.Header.Get("Hit-Handler") != "1" { 3986 out, err := httputil.DumpResponse(res, true) 3987 if err != nil { 3988 t.Fatal(err) 3989 } 3990 t.Errorf("Response body wasn't from Handler. Got:\n%s\n", out) 3991 } 3992 } 3993 3994 // Issue 13290: send User-Agent in proxy CONNECT 3995 func TestTransportProxyConnectHeader(t *testing.T) { 3996 defer afterTest(t) 3997 reqc := make(chan *Request, 1) 3998 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3999 if r.Method != "CONNECT" { 4000 t.Errorf("method = %q; want CONNECT", r.Method) 4001 } 4002 reqc <- r 4003 c, _, err := w.(Hijacker).Hijack() 4004 if err != nil { 4005 t.Errorf("Hijack: %v", err) 4006 return 4007 } 4008 c.Close() 4009 })) 4010 defer ts.Close() 4011 4012 c := ts.Client() 4013 c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) { 4014 return url.Parse(ts.URL) 4015 } 4016 c.Transport.(*Transport).ProxyConnectHeader = Header{ 4017 "User-Agent": {"foo"}, 4018 "Other": {"bar"}, 4019 } 4020 4021 res, err := c.Get("https://dummy.tld/") // https to force a CONNECT 4022 if err == nil { 4023 res.Body.Close() 4024 t.Errorf("unexpected success") 4025 } 4026 select { 4027 case <-time.After(3 * time.Second): 4028 t.Fatal("timeout") 4029 case r := <-reqc: 4030 if got, want := r.Header.Get("User-Agent"), "foo"; got != want { 4031 t.Errorf("CONNECT request User-Agent = %q; want %q", got, want) 4032 } 4033 if got, want := r.Header.Get("Other"), "bar"; got != want { 4034 t.Errorf("CONNECT request Other = %q; want %q", got, want) 4035 } 4036 } 4037 } 4038 4039 var errFakeRoundTrip = errors.New("fake roundtrip") 4040 4041 type funcRoundTripper func() 4042 4043 func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) { 4044 fn() 4045 return nil, errFakeRoundTrip 4046 } 4047 4048 func wantBody(res *Response, err error, want string) error { 4049 if err != nil { 4050 return err 4051 } 4052 slurp, err := ioutil.ReadAll(res.Body) 4053 if err != nil { 4054 return fmt.Errorf("error reading body: %v", err) 4055 } 4056 if string(slurp) != want { 4057 return fmt.Errorf("body = %q; want %q", slurp, want) 4058 } 4059 if err := res.Body.Close(); err != nil { 4060 return fmt.Errorf("body Close = %v", err) 4061 } 4062 return nil 4063 } 4064 4065 func newLocalListener(t *testing.T) net.Listener { 4066 ln, err := net.Listen("tcp", "127.0.0.1:0") 4067 if err != nil { 4068 ln, err = net.Listen("tcp6", "[::1]:0") 4069 } 4070 if err != nil { 4071 t.Fatal(err) 4072 } 4073 return ln 4074 } 4075 4076 type countCloseReader struct { 4077 n *int 4078 io.Reader 4079 } 4080 4081 func (cr countCloseReader) Close() error { 4082 (*cr.n)++ 4083 return nil 4084 } 4085 4086 // rgz is a gzip quine that uncompresses to itself. 4087 var rgz = []byte{ 4088 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 4089 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 4090 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 4091 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 4092 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 4093 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 4094 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 4095 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 4096 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 4097 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 4098 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 4099 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 4100 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 4101 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 4102 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 4103 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 4104 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 4105 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 4106 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 4107 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 4108 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 4109 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 4110 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 4111 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 4112 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 4113 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 4114 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 4115 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 4116 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 4117 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 4118 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 4119 0x00, 0x00, 4120 }