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