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 l := newLocalListener(t) 965 defer l.Close() 966 defer close(ch) 967 proxy := func(t *testing.T) { 968 s, err := l.Accept() 969 if err != nil { 970 t.Errorf("socks5 proxy Accept(): %v", err) 971 return 972 } 973 defer s.Close() 974 var buf [22]byte 975 if _, err := io.ReadFull(s, buf[:3]); err != nil { 976 t.Errorf("socks5 proxy initial read: %v", err) 977 return 978 } 979 if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) { 980 t.Errorf("socks5 proxy initial read: got %v, want %v", buf[:3], want) 981 return 982 } 983 if _, err := s.Write([]byte{5, 0}); err != nil { 984 t.Errorf("socks5 proxy initial write: %v", err) 985 return 986 } 987 if _, err := io.ReadFull(s, buf[:4]); err != nil { 988 t.Errorf("socks5 proxy second read: %v", err) 989 return 990 } 991 if want := []byte{5, 1, 0}; !bytes.Equal(buf[:3], want) { 992 t.Errorf("socks5 proxy second read: got %v, want %v", buf[:3], want) 993 return 994 } 995 var ipLen int 996 switch buf[3] { 997 case 1: 998 ipLen = 4 999 case 4: 1000 ipLen = 16 1001 default: 1002 t.Errorf("socks5 proxy second read: unexpected address type %v", buf[4]) 1003 return 1004 } 1005 if _, err := io.ReadFull(s, buf[4:ipLen+6]); err != nil { 1006 t.Errorf("socks5 proxy address read: %v", err) 1007 return 1008 } 1009 ip := net.IP(buf[4 : ipLen+4]) 1010 port := binary.BigEndian.Uint16(buf[ipLen+4 : ipLen+6]) 1011 copy(buf[:3], []byte{5, 0, 0}) 1012 if _, err := s.Write(buf[:ipLen+6]); err != nil { 1013 t.Errorf("socks5 proxy connect write: %v", err) 1014 return 1015 } 1016 ch <- fmt.Sprintf("proxy for %s:%d", ip, port) 1017 1018 // Implement proxying. 1019 targetHost := net.JoinHostPort(ip.String(), strconv.Itoa(int(port))) 1020 targetConn, err := net.Dial("tcp", targetHost) 1021 if err != nil { 1022 t.Errorf("net.Dial failed") 1023 return 1024 } 1025 go io.Copy(targetConn, s) 1026 io.Copy(s, targetConn) // Wait for the client to close the socket. 1027 targetConn.Close() 1028 } 1029 1030 pu, err := url.Parse("socks5://" + l.Addr().String()) 1031 if err != nil { 1032 t.Fatal(err) 1033 } 1034 1035 sentinelHeader := "X-Sentinel" 1036 sentinelValue := "12345" 1037 h := HandlerFunc(func(w ResponseWriter, r *Request) { 1038 w.Header().Set(sentinelHeader, sentinelValue) 1039 }) 1040 for _, useTLS := range []bool{false, true} { 1041 t.Run(fmt.Sprintf("useTLS=%v", useTLS), func(t *testing.T) { 1042 var ts *httptest.Server 1043 if useTLS { 1044 ts = httptest.NewTLSServer(h) 1045 } else { 1046 ts = httptest.NewServer(h) 1047 } 1048 go proxy(t) 1049 c := ts.Client() 1050 c.Transport.(*Transport).Proxy = ProxyURL(pu) 1051 r, err := c.Head(ts.URL) 1052 if err != nil { 1053 t.Fatal(err) 1054 } 1055 if r.Header.Get(sentinelHeader) != sentinelValue { 1056 t.Errorf("Failed to retrieve sentinel value") 1057 } 1058 var got string 1059 select { 1060 case got = <-ch: 1061 case <-time.After(5 * time.Second): 1062 t.Fatal("timeout connecting to socks5 proxy") 1063 } 1064 ts.Close() 1065 tsu, err := url.Parse(ts.URL) 1066 if err != nil { 1067 t.Fatal(err) 1068 } 1069 want := "proxy for " + tsu.Host 1070 if got != want { 1071 t.Errorf("got %q, want %q", got, want) 1072 } 1073 }) 1074 } 1075 } 1076 1077 func TestTransportProxy(t *testing.T) { 1078 defer afterTest(t) 1079 testCases := []struct{ httpsSite, httpsProxy bool }{ 1080 {false, false}, 1081 {false, true}, 1082 {true, false}, 1083 {true, true}, 1084 } 1085 for _, testCase := range testCases { 1086 httpsSite := testCase.httpsSite 1087 httpsProxy := testCase.httpsProxy 1088 t.Run(fmt.Sprintf("httpsSite=%v, httpsProxy=%v", httpsSite, httpsProxy), func(t *testing.T) { 1089 siteCh := make(chan *Request, 1) 1090 h1 := HandlerFunc(func(w ResponseWriter, r *Request) { 1091 siteCh <- r 1092 }) 1093 proxyCh := make(chan *Request, 1) 1094 h2 := HandlerFunc(func(w ResponseWriter, r *Request) { 1095 proxyCh <- r 1096 // Implement an entire CONNECT proxy 1097 if r.Method == "CONNECT" { 1098 hijacker, ok := w.(Hijacker) 1099 if !ok { 1100 t.Errorf("hijack not allowed") 1101 return 1102 } 1103 clientConn, _, err := hijacker.Hijack() 1104 if err != nil { 1105 t.Errorf("hijacking failed") 1106 return 1107 } 1108 res := &Response{ 1109 StatusCode: StatusOK, 1110 Proto: "HTTP/1.1", 1111 ProtoMajor: 1, 1112 ProtoMinor: 1, 1113 Header: make(Header), 1114 } 1115 1116 targetConn, err := net.Dial("tcp", r.URL.Host) 1117 if err != nil { 1118 t.Errorf("net.Dial(%q) failed: %v", r.URL.Host, err) 1119 return 1120 } 1121 1122 if err := res.Write(clientConn); err != nil { 1123 t.Errorf("Writing 200 OK failed: %v", err) 1124 return 1125 } 1126 1127 go io.Copy(targetConn, clientConn) 1128 go func() { 1129 io.Copy(clientConn, targetConn) 1130 targetConn.Close() 1131 }() 1132 } 1133 }) 1134 var ts *httptest.Server 1135 if httpsSite { 1136 ts = httptest.NewTLSServer(h1) 1137 } else { 1138 ts = httptest.NewServer(h1) 1139 } 1140 var proxy *httptest.Server 1141 if httpsProxy { 1142 proxy = httptest.NewTLSServer(h2) 1143 } else { 1144 proxy = httptest.NewServer(h2) 1145 } 1146 1147 pu, err := url.Parse(proxy.URL) 1148 if err != nil { 1149 t.Fatal(err) 1150 } 1151 1152 // If neither server is HTTPS or both are, then c may be derived from either. 1153 // If only one server is HTTPS, c must be derived from that server in order 1154 // to ensure that it is configured to use the fake root CA from testcert.go. 1155 c := proxy.Client() 1156 if httpsSite { 1157 c = ts.Client() 1158 } 1159 1160 c.Transport.(*Transport).Proxy = ProxyURL(pu) 1161 if _, err := c.Head(ts.URL); err != nil { 1162 t.Error(err) 1163 } 1164 var got *Request 1165 select { 1166 case got = <-proxyCh: 1167 case <-time.After(5 * time.Second): 1168 t.Fatal("timeout connecting to http proxy") 1169 } 1170 c.Transport.(*Transport).CloseIdleConnections() 1171 ts.Close() 1172 proxy.Close() 1173 if httpsSite { 1174 // First message should be a CONNECT, asking for a socket to the real server, 1175 if got.Method != "CONNECT" { 1176 t.Errorf("Wrong method for secure proxying: %q", got.Method) 1177 } 1178 gotHost := got.URL.Host 1179 pu, err := url.Parse(ts.URL) 1180 if err != nil { 1181 t.Fatal("Invalid site URL") 1182 } 1183 if wantHost := pu.Host; gotHost != wantHost { 1184 t.Errorf("Got CONNECT host %q, want %q", gotHost, wantHost) 1185 } 1186 1187 // The next message on the channel should be from the site's server. 1188 next := <-siteCh 1189 if next.Method != "HEAD" { 1190 t.Errorf("Wrong method at destination: %s", next.Method) 1191 } 1192 if nextURL := next.URL.String(); nextURL != "/" { 1193 t.Errorf("Wrong URL at destination: %s", nextURL) 1194 } 1195 } else { 1196 if got.Method != "HEAD" { 1197 t.Errorf("Wrong method for destination: %q", got.Method) 1198 } 1199 gotURL := got.URL.String() 1200 wantURL := ts.URL + "/" 1201 if gotURL != wantURL { 1202 t.Errorf("Got URL %q, want %q", gotURL, wantURL) 1203 } 1204 } 1205 }) 1206 } 1207 } 1208 1209 // Issue 16997: test transport dial preserves typed errors 1210 func TestTransportDialPreservesNetOpProxyError(t *testing.T) { 1211 defer afterTest(t) 1212 1213 var errDial = errors.New("some dial error") 1214 1215 tr := &Transport{ 1216 Proxy: func(*Request) (*url.URL, error) { 1217 return url.Parse("http://proxy.fake.tld/") 1218 }, 1219 Dial: func(string, string) (net.Conn, error) { 1220 return nil, errDial 1221 }, 1222 } 1223 defer tr.CloseIdleConnections() 1224 1225 c := &Client{Transport: tr} 1226 req, _ := NewRequest("GET", "http://fake.tld", nil) 1227 res, err := c.Do(req) 1228 if err == nil { 1229 res.Body.Close() 1230 t.Fatal("wanted a non-nil error") 1231 } 1232 1233 uerr, ok := err.(*url.Error) 1234 if !ok { 1235 t.Fatalf("got %T, want *url.Error", err) 1236 } 1237 oe, ok := uerr.Err.(*net.OpError) 1238 if !ok { 1239 t.Fatalf("url.Error.Err = %T; want *net.OpError", uerr.Err) 1240 } 1241 want := &net.OpError{ 1242 Op: "proxyconnect", 1243 Net: "tcp", 1244 Err: errDial, // original error, unwrapped. 1245 } 1246 if !reflect.DeepEqual(oe, want) { 1247 t.Errorf("Got error %#v; want %#v", oe, want) 1248 } 1249 } 1250 1251 // TestTransportGzipRecursive sends a gzip quine and checks that the 1252 // client gets the same value back. This is more cute than anything, 1253 // but checks that we don't recurse forever, and checks that 1254 // Content-Encoding is removed. 1255 func TestTransportGzipRecursive(t *testing.T) { 1256 defer afterTest(t) 1257 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1258 w.Header().Set("Content-Encoding", "gzip") 1259 w.Write(rgz) 1260 })) 1261 defer ts.Close() 1262 1263 c := ts.Client() 1264 res, err := c.Get(ts.URL) 1265 if err != nil { 1266 t.Fatal(err) 1267 } 1268 body, err := ioutil.ReadAll(res.Body) 1269 if err != nil { 1270 t.Fatal(err) 1271 } 1272 if !bytes.Equal(body, rgz) { 1273 t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x", 1274 body, rgz) 1275 } 1276 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 1277 t.Fatalf("Content-Encoding = %q; want %q", g, e) 1278 } 1279 } 1280 1281 // golang.org/issue/7750: request fails when server replies with 1282 // a short gzip body 1283 func TestTransportGzipShort(t *testing.T) { 1284 defer afterTest(t) 1285 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1286 w.Header().Set("Content-Encoding", "gzip") 1287 w.Write([]byte{0x1f, 0x8b}) 1288 })) 1289 defer ts.Close() 1290 1291 c := ts.Client() 1292 res, err := c.Get(ts.URL) 1293 if err != nil { 1294 t.Fatal(err) 1295 } 1296 defer res.Body.Close() 1297 _, err = ioutil.ReadAll(res.Body) 1298 if err == nil { 1299 t.Fatal("Expect an error from reading a body.") 1300 } 1301 if err != io.ErrUnexpectedEOF { 1302 t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err) 1303 } 1304 } 1305 1306 // Wait until number of goroutines is no greater than nmax, or time out. 1307 func waitNumGoroutine(nmax int) int { 1308 nfinal := runtime.NumGoroutine() 1309 for ntries := 10; ntries > 0 && nfinal > nmax; ntries-- { 1310 time.Sleep(50 * time.Millisecond) 1311 runtime.GC() 1312 nfinal = runtime.NumGoroutine() 1313 } 1314 return nfinal 1315 } 1316 1317 // tests that persistent goroutine connections shut down when no longer desired. 1318 func TestTransportPersistConnLeak(t *testing.T) { 1319 // Not parallel: counts goroutines 1320 defer afterTest(t) 1321 1322 const numReq = 25 1323 gotReqCh := make(chan bool, numReq) 1324 unblockCh := make(chan bool, numReq) 1325 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1326 gotReqCh <- true 1327 <-unblockCh 1328 w.Header().Set("Content-Length", "0") 1329 w.WriteHeader(204) 1330 })) 1331 defer ts.Close() 1332 c := ts.Client() 1333 tr := c.Transport.(*Transport) 1334 1335 n0 := runtime.NumGoroutine() 1336 1337 didReqCh := make(chan bool, numReq) 1338 failed := make(chan bool, numReq) 1339 for i := 0; i < numReq; i++ { 1340 go func() { 1341 res, err := c.Get(ts.URL) 1342 didReqCh <- true 1343 if err != nil { 1344 t.Errorf("client fetch error: %v", err) 1345 failed <- true 1346 return 1347 } 1348 res.Body.Close() 1349 }() 1350 } 1351 1352 // Wait for all goroutines to be stuck in the Handler. 1353 for i := 0; i < numReq; i++ { 1354 select { 1355 case <-gotReqCh: 1356 // ok 1357 case <-failed: 1358 close(unblockCh) 1359 return 1360 } 1361 } 1362 1363 nhigh := runtime.NumGoroutine() 1364 1365 // Tell all handlers to unblock and reply. 1366 for i := 0; i < numReq; i++ { 1367 unblockCh <- true 1368 } 1369 1370 // Wait for all HTTP clients to be done. 1371 for i := 0; i < numReq; i++ { 1372 <-didReqCh 1373 } 1374 1375 tr.CloseIdleConnections() 1376 nfinal := waitNumGoroutine(n0 + 5) 1377 1378 growth := nfinal - n0 1379 1380 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 1381 // Previously we were leaking one per numReq. 1382 if int(growth) > 5 { 1383 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 1384 t.Error("too many new goroutines") 1385 } 1386 } 1387 1388 // golang.org/issue/4531: Transport leaks goroutines when 1389 // request.ContentLength is explicitly short 1390 func TestTransportPersistConnLeakShortBody(t *testing.T) { 1391 // Not parallel: measures goroutines. 1392 defer afterTest(t) 1393 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1394 })) 1395 defer ts.Close() 1396 c := ts.Client() 1397 tr := c.Transport.(*Transport) 1398 1399 n0 := runtime.NumGoroutine() 1400 body := []byte("Hello") 1401 for i := 0; i < 20; i++ { 1402 req, err := NewRequest("POST", ts.URL, bytes.NewReader(body)) 1403 if err != nil { 1404 t.Fatal(err) 1405 } 1406 req.ContentLength = int64(len(body) - 2) // explicitly short 1407 _, err = c.Do(req) 1408 if err == nil { 1409 t.Fatal("Expect an error from writing too long of a body.") 1410 } 1411 } 1412 nhigh := runtime.NumGoroutine() 1413 tr.CloseIdleConnections() 1414 nfinal := waitNumGoroutine(n0 + 5) 1415 1416 growth := nfinal - n0 1417 1418 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 1419 // Previously we were leaking one per numReq. 1420 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 1421 if int(growth) > 5 { 1422 t.Error("too many new goroutines") 1423 } 1424 } 1425 1426 // This used to crash; https://golang.org/issue/3266 1427 func TestTransportIdleConnCrash(t *testing.T) { 1428 defer afterTest(t) 1429 var tr *Transport 1430 1431 unblockCh := make(chan bool, 1) 1432 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1433 <-unblockCh 1434 tr.CloseIdleConnections() 1435 })) 1436 defer ts.Close() 1437 c := ts.Client() 1438 tr = c.Transport.(*Transport) 1439 1440 didreq := make(chan bool) 1441 go func() { 1442 res, err := c.Get(ts.URL) 1443 if err != nil { 1444 t.Error(err) 1445 } else { 1446 res.Body.Close() // returns idle conn 1447 } 1448 didreq <- true 1449 }() 1450 unblockCh <- true 1451 <-didreq 1452 } 1453 1454 // Test that the transport doesn't close the TCP connection early, 1455 // before the response body has been read. This was a regression 1456 // which sadly lacked a triggering test. The large response body made 1457 // the old race easier to trigger. 1458 func TestIssue3644(t *testing.T) { 1459 defer afterTest(t) 1460 const numFoos = 5000 1461 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1462 w.Header().Set("Connection", "close") 1463 for i := 0; i < numFoos; i++ { 1464 w.Write([]byte("foo ")) 1465 } 1466 })) 1467 defer ts.Close() 1468 c := ts.Client() 1469 res, err := c.Get(ts.URL) 1470 if err != nil { 1471 t.Fatal(err) 1472 } 1473 defer res.Body.Close() 1474 bs, err := ioutil.ReadAll(res.Body) 1475 if err != nil { 1476 t.Fatal(err) 1477 } 1478 if len(bs) != numFoos*len("foo ") { 1479 t.Errorf("unexpected response length") 1480 } 1481 } 1482 1483 // Test that a client receives a server's reply, even if the server doesn't read 1484 // the entire request body. 1485 func TestIssue3595(t *testing.T) { 1486 setParallel(t) 1487 defer afterTest(t) 1488 const deniedMsg = "sorry, denied." 1489 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1490 Error(w, deniedMsg, StatusUnauthorized) 1491 })) 1492 defer ts.Close() 1493 c := ts.Client() 1494 res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a')) 1495 if err != nil { 1496 t.Errorf("Post: %v", err) 1497 return 1498 } 1499 got, err := ioutil.ReadAll(res.Body) 1500 if err != nil { 1501 t.Fatalf("Body ReadAll: %v", err) 1502 } 1503 if !strings.Contains(string(got), deniedMsg) { 1504 t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg) 1505 } 1506 } 1507 1508 // From https://golang.org/issue/4454 , 1509 // "client fails to handle requests with no body and chunked encoding" 1510 func TestChunkedNoContent(t *testing.T) { 1511 defer afterTest(t) 1512 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1513 w.WriteHeader(StatusNoContent) 1514 })) 1515 defer ts.Close() 1516 1517 c := ts.Client() 1518 for _, closeBody := range []bool{true, false} { 1519 const n = 4 1520 for i := 1; i <= n; i++ { 1521 res, err := c.Get(ts.URL) 1522 if err != nil { 1523 t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err) 1524 } else { 1525 if closeBody { 1526 res.Body.Close() 1527 } 1528 } 1529 } 1530 } 1531 } 1532 1533 func TestTransportConcurrency(t *testing.T) { 1534 // Not parallel: uses global test hooks. 1535 defer afterTest(t) 1536 maxProcs, numReqs := 16, 500 1537 if testing.Short() { 1538 maxProcs, numReqs = 4, 50 1539 } 1540 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1541 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1542 fmt.Fprintf(w, "%v", r.FormValue("echo")) 1543 })) 1544 defer ts.Close() 1545 1546 var wg sync.WaitGroup 1547 wg.Add(numReqs) 1548 1549 // Due to the Transport's "socket late binding" (see 1550 // idleConnCh in transport.go), the numReqs HTTP requests 1551 // below can finish with a dial still outstanding. To keep 1552 // the leak checker happy, keep track of pending dials and 1553 // wait for them to finish (and be closed or returned to the 1554 // idle pool) before we close idle connections. 1555 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done) 1556 defer SetPendingDialHooks(nil, nil) 1557 1558 c := ts.Client() 1559 reqs := make(chan string) 1560 defer close(reqs) 1561 1562 for i := 0; i < maxProcs*2; i++ { 1563 go func() { 1564 for req := range reqs { 1565 res, err := c.Get(ts.URL + "/?echo=" + req) 1566 if err != nil { 1567 t.Errorf("error on req %s: %v", req, err) 1568 wg.Done() 1569 continue 1570 } 1571 all, err := ioutil.ReadAll(res.Body) 1572 if err != nil { 1573 t.Errorf("read error on req %s: %v", req, err) 1574 wg.Done() 1575 continue 1576 } 1577 if string(all) != req { 1578 t.Errorf("body of req %s = %q; want %q", req, all, req) 1579 } 1580 res.Body.Close() 1581 wg.Done() 1582 } 1583 }() 1584 } 1585 for i := 0; i < numReqs; i++ { 1586 reqs <- fmt.Sprintf("request-%d", i) 1587 } 1588 wg.Wait() 1589 } 1590 1591 func TestIssue4191_InfiniteGetTimeout(t *testing.T) { 1592 setParallel(t) 1593 defer afterTest(t) 1594 const debug = false 1595 mux := NewServeMux() 1596 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1597 io.Copy(w, neverEnding('a')) 1598 }) 1599 ts := httptest.NewServer(mux) 1600 defer ts.Close() 1601 timeout := 100 * time.Millisecond 1602 1603 c := ts.Client() 1604 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) { 1605 conn, err := net.Dial(n, addr) 1606 if err != nil { 1607 return nil, err 1608 } 1609 conn.SetDeadline(time.Now().Add(timeout)) 1610 if debug { 1611 conn = NewLoggingConn("client", conn) 1612 } 1613 return conn, nil 1614 } 1615 1616 getFailed := false 1617 nRuns := 5 1618 if testing.Short() { 1619 nRuns = 1 1620 } 1621 for i := 0; i < nRuns; i++ { 1622 if debug { 1623 println("run", i+1, "of", nRuns) 1624 } 1625 sres, err := c.Get(ts.URL + "/get") 1626 if err != nil { 1627 if !getFailed { 1628 // Make the timeout longer, once. 1629 getFailed = true 1630 t.Logf("increasing timeout") 1631 i-- 1632 timeout *= 10 1633 continue 1634 } 1635 t.Errorf("Error issuing GET: %v", err) 1636 break 1637 } 1638 _, err = io.Copy(ioutil.Discard, sres.Body) 1639 if err == nil { 1640 t.Errorf("Unexpected successful copy") 1641 break 1642 } 1643 } 1644 if debug { 1645 println("tests complete; waiting for handlers to finish") 1646 } 1647 } 1648 1649 func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) { 1650 setParallel(t) 1651 defer afterTest(t) 1652 const debug = false 1653 mux := NewServeMux() 1654 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1655 io.Copy(w, neverEnding('a')) 1656 }) 1657 mux.HandleFunc("/put", func(w ResponseWriter, r *Request) { 1658 defer r.Body.Close() 1659 io.Copy(ioutil.Discard, r.Body) 1660 }) 1661 ts := httptest.NewServer(mux) 1662 timeout := 100 * time.Millisecond 1663 1664 c := ts.Client() 1665 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) { 1666 conn, err := net.Dial(n, addr) 1667 if err != nil { 1668 return nil, err 1669 } 1670 conn.SetDeadline(time.Now().Add(timeout)) 1671 if debug { 1672 conn = NewLoggingConn("client", conn) 1673 } 1674 return conn, nil 1675 } 1676 1677 getFailed := false 1678 nRuns := 5 1679 if testing.Short() { 1680 nRuns = 1 1681 } 1682 for i := 0; i < nRuns; i++ { 1683 if debug { 1684 println("run", i+1, "of", nRuns) 1685 } 1686 sres, err := c.Get(ts.URL + "/get") 1687 if err != nil { 1688 if !getFailed { 1689 // Make the timeout longer, once. 1690 getFailed = true 1691 t.Logf("increasing timeout") 1692 i-- 1693 timeout *= 10 1694 continue 1695 } 1696 t.Errorf("Error issuing GET: %v", err) 1697 break 1698 } 1699 req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body) 1700 _, err = c.Do(req) 1701 if err == nil { 1702 sres.Body.Close() 1703 t.Errorf("Unexpected successful PUT") 1704 break 1705 } 1706 sres.Body.Close() 1707 } 1708 if debug { 1709 println("tests complete; waiting for handlers to finish") 1710 } 1711 ts.Close() 1712 } 1713 1714 func TestTransportResponseHeaderTimeout(t *testing.T) { 1715 setParallel(t) 1716 defer afterTest(t) 1717 if testing.Short() { 1718 t.Skip("skipping timeout test in -short mode") 1719 } 1720 inHandler := make(chan bool, 1) 1721 mux := NewServeMux() 1722 mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) { 1723 inHandler <- true 1724 }) 1725 mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) { 1726 inHandler <- true 1727 time.Sleep(2 * time.Second) 1728 }) 1729 ts := httptest.NewServer(mux) 1730 defer ts.Close() 1731 1732 c := ts.Client() 1733 c.Transport.(*Transport).ResponseHeaderTimeout = 500 * time.Millisecond 1734 1735 tests := []struct { 1736 path string 1737 want int 1738 wantErr string 1739 }{ 1740 {path: "/fast", want: 200}, 1741 {path: "/slow", wantErr: "timeout awaiting response headers"}, 1742 {path: "/fast", want: 200}, 1743 } 1744 for i, tt := range tests { 1745 req, _ := NewRequest("GET", ts.URL+tt.path, nil) 1746 req = req.WithT(t) 1747 res, err := c.Do(req) 1748 select { 1749 case <-inHandler: 1750 case <-time.After(5 * time.Second): 1751 t.Errorf("never entered handler for test index %d, %s", i, tt.path) 1752 continue 1753 } 1754 if err != nil { 1755 uerr, ok := err.(*url.Error) 1756 if !ok { 1757 t.Errorf("error is not an url.Error; got: %#v", err) 1758 continue 1759 } 1760 nerr, ok := uerr.Err.(net.Error) 1761 if !ok { 1762 t.Errorf("error does not satisfy net.Error interface; got: %#v", err) 1763 continue 1764 } 1765 if !nerr.Timeout() { 1766 t.Errorf("want timeout error; got: %q", nerr) 1767 continue 1768 } 1769 if strings.Contains(err.Error(), tt.wantErr) { 1770 continue 1771 } 1772 t.Errorf("%d. unexpected error: %v", i, err) 1773 continue 1774 } 1775 if tt.wantErr != "" { 1776 t.Errorf("%d. no error. expected error: %v", i, tt.wantErr) 1777 continue 1778 } 1779 if res.StatusCode != tt.want { 1780 t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want) 1781 } 1782 } 1783 } 1784 1785 func TestTransportCancelRequest(t *testing.T) { 1786 setParallel(t) 1787 defer afterTest(t) 1788 if testing.Short() { 1789 t.Skip("skipping test in -short mode") 1790 } 1791 unblockc := make(chan bool) 1792 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1793 fmt.Fprintf(w, "Hello") 1794 w.(Flusher).Flush() // send headers and some body 1795 <-unblockc 1796 })) 1797 defer ts.Close() 1798 defer close(unblockc) 1799 1800 c := ts.Client() 1801 tr := c.Transport.(*Transport) 1802 1803 req, _ := NewRequest("GET", ts.URL, nil) 1804 res, err := c.Do(req) 1805 if err != nil { 1806 t.Fatal(err) 1807 } 1808 go func() { 1809 time.Sleep(1 * time.Second) 1810 tr.CancelRequest(req) 1811 }() 1812 t0 := time.Now() 1813 body, err := ioutil.ReadAll(res.Body) 1814 d := time.Since(t0) 1815 1816 if err != ExportErrRequestCanceled { 1817 t.Errorf("Body.Read error = %v; want errRequestCanceled", err) 1818 } 1819 if string(body) != "Hello" { 1820 t.Errorf("Body = %q; want Hello", body) 1821 } 1822 if d < 500*time.Millisecond { 1823 t.Errorf("expected ~1 second delay; got %v", d) 1824 } 1825 // Verify no outstanding requests after readLoop/writeLoop 1826 // goroutines shut down. 1827 for tries := 5; tries > 0; tries-- { 1828 n := tr.NumPendingRequestsForTesting() 1829 if n == 0 { 1830 break 1831 } 1832 time.Sleep(100 * time.Millisecond) 1833 if tries == 1 { 1834 t.Errorf("pending requests = %d; want 0", n) 1835 } 1836 } 1837 } 1838 1839 func TestTransportCancelRequestInDial(t *testing.T) { 1840 defer afterTest(t) 1841 if testing.Short() { 1842 t.Skip("skipping test in -short mode") 1843 } 1844 var logbuf bytes.Buffer 1845 eventLog := log.New(&logbuf, "", 0) 1846 1847 unblockDial := make(chan bool) 1848 defer close(unblockDial) 1849 1850 inDial := make(chan bool) 1851 tr := &Transport{ 1852 Dial: func(network, addr string) (net.Conn, error) { 1853 eventLog.Println("dial: blocking") 1854 inDial <- true 1855 <-unblockDial 1856 return nil, errors.New("nope") 1857 }, 1858 } 1859 cl := &Client{Transport: tr} 1860 gotres := make(chan bool) 1861 req, _ := NewRequest("GET", "http://something.no-network.tld/", nil) 1862 go func() { 1863 _, err := cl.Do(req) 1864 eventLog.Printf("Get = %v", err) 1865 gotres <- true 1866 }() 1867 1868 select { 1869 case <-inDial: 1870 case <-time.After(5 * time.Second): 1871 t.Fatal("timeout; never saw blocking dial") 1872 } 1873 1874 eventLog.Printf("canceling") 1875 tr.CancelRequest(req) 1876 tr.CancelRequest(req) // used to panic on second call 1877 1878 select { 1879 case <-gotres: 1880 case <-time.After(5 * time.Second): 1881 panic("hang. events are: " + logbuf.String()) 1882 } 1883 1884 got := logbuf.String() 1885 want := `dial: blocking 1886 canceling 1887 Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection 1888 ` 1889 if got != want { 1890 t.Errorf("Got events:\n%s\nWant:\n%s", got, want) 1891 } 1892 } 1893 1894 func TestCancelRequestWithChannel(t *testing.T) { 1895 setParallel(t) 1896 defer afterTest(t) 1897 if testing.Short() { 1898 t.Skip("skipping test in -short mode") 1899 } 1900 unblockc := make(chan bool) 1901 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1902 fmt.Fprintf(w, "Hello") 1903 w.(Flusher).Flush() // send headers and some body 1904 <-unblockc 1905 })) 1906 defer ts.Close() 1907 defer close(unblockc) 1908 1909 c := ts.Client() 1910 tr := c.Transport.(*Transport) 1911 1912 req, _ := NewRequest("GET", ts.URL, nil) 1913 ch := make(chan struct{}) 1914 req.Cancel = ch 1915 1916 res, err := c.Do(req) 1917 if err != nil { 1918 t.Fatal(err) 1919 } 1920 go func() { 1921 time.Sleep(1 * time.Second) 1922 close(ch) 1923 }() 1924 t0 := time.Now() 1925 body, err := ioutil.ReadAll(res.Body) 1926 d := time.Since(t0) 1927 1928 if err != ExportErrRequestCanceled { 1929 t.Errorf("Body.Read error = %v; want errRequestCanceled", err) 1930 } 1931 if string(body) != "Hello" { 1932 t.Errorf("Body = %q; want Hello", body) 1933 } 1934 if d < 500*time.Millisecond { 1935 t.Errorf("expected ~1 second delay; got %v", d) 1936 } 1937 // Verify no outstanding requests after readLoop/writeLoop 1938 // goroutines shut down. 1939 for tries := 5; tries > 0; tries-- { 1940 n := tr.NumPendingRequestsForTesting() 1941 if n == 0 { 1942 break 1943 } 1944 time.Sleep(100 * time.Millisecond) 1945 if tries == 1 { 1946 t.Errorf("pending requests = %d; want 0", n) 1947 } 1948 } 1949 } 1950 1951 func TestCancelRequestWithChannelBeforeDo_Cancel(t *testing.T) { 1952 testCancelRequestWithChannelBeforeDo(t, false) 1953 } 1954 func TestCancelRequestWithChannelBeforeDo_Context(t *testing.T) { 1955 testCancelRequestWithChannelBeforeDo(t, true) 1956 } 1957 func testCancelRequestWithChannelBeforeDo(t *testing.T, withCtx bool) { 1958 setParallel(t) 1959 defer afterTest(t) 1960 unblockc := make(chan bool) 1961 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1962 <-unblockc 1963 })) 1964 defer ts.Close() 1965 defer close(unblockc) 1966 1967 c := ts.Client() 1968 1969 req, _ := NewRequest("GET", ts.URL, nil) 1970 if withCtx { 1971 ctx, cancel := context.WithCancel(context.Background()) 1972 cancel() 1973 req = req.WithContext(ctx) 1974 } else { 1975 ch := make(chan struct{}) 1976 req.Cancel = ch 1977 close(ch) 1978 } 1979 1980 _, err := c.Do(req) 1981 if ue, ok := err.(*url.Error); ok { 1982 err = ue.Err 1983 } 1984 if withCtx { 1985 if err != context.Canceled { 1986 t.Errorf("Do error = %v; want %v", err, context.Canceled) 1987 } 1988 } else { 1989 if err == nil || !strings.Contains(err.Error(), "canceled") { 1990 t.Errorf("Do error = %v; want cancelation", err) 1991 } 1992 } 1993 } 1994 1995 // Issue 11020. The returned error message should be errRequestCanceled 1996 func TestTransportCancelBeforeResponseHeaders(t *testing.T) { 1997 defer afterTest(t) 1998 1999 serverConnCh := make(chan net.Conn, 1) 2000 tr := &Transport{ 2001 Dial: func(network, addr string) (net.Conn, error) { 2002 cc, sc := net.Pipe() 2003 serverConnCh <- sc 2004 return cc, nil 2005 }, 2006 } 2007 defer tr.CloseIdleConnections() 2008 errc := make(chan error, 1) 2009 req, _ := NewRequest("GET", "http://example.com/", nil) 2010 go func() { 2011 _, err := tr.RoundTrip(req) 2012 errc <- err 2013 }() 2014 2015 sc := <-serverConnCh 2016 verb := make([]byte, 3) 2017 if _, err := io.ReadFull(sc, verb); err != nil { 2018 t.Errorf("Error reading HTTP verb from server: %v", err) 2019 } 2020 if string(verb) != "GET" { 2021 t.Errorf("server received %q; want GET", verb) 2022 } 2023 defer sc.Close() 2024 2025 tr.CancelRequest(req) 2026 2027 err := <-errc 2028 if err == nil { 2029 t.Fatalf("unexpected success from RoundTrip") 2030 } 2031 if err != ExportErrRequestCanceled { 2032 t.Errorf("RoundTrip error = %v; want ExportErrRequestCanceled", err) 2033 } 2034 } 2035 2036 // golang.org/issue/3672 -- Client can't close HTTP stream 2037 // Calling Close on a Response.Body used to just read until EOF. 2038 // Now it actually closes the TCP connection. 2039 func TestTransportCloseResponseBody(t *testing.T) { 2040 defer afterTest(t) 2041 writeErr := make(chan error, 1) 2042 msg := []byte("young\n") 2043 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2044 for { 2045 _, err := w.Write(msg) 2046 if err != nil { 2047 writeErr <- err 2048 return 2049 } 2050 w.(Flusher).Flush() 2051 } 2052 })) 2053 defer ts.Close() 2054 2055 c := ts.Client() 2056 tr := c.Transport.(*Transport) 2057 2058 req, _ := NewRequest("GET", ts.URL, nil) 2059 defer tr.CancelRequest(req) 2060 2061 res, err := c.Do(req) 2062 if err != nil { 2063 t.Fatal(err) 2064 } 2065 2066 const repeats = 3 2067 buf := make([]byte, len(msg)*repeats) 2068 want := bytes.Repeat(msg, repeats) 2069 2070 _, err = io.ReadFull(res.Body, buf) 2071 if err != nil { 2072 t.Fatal(err) 2073 } 2074 if !bytes.Equal(buf, want) { 2075 t.Fatalf("read %q; want %q", buf, want) 2076 } 2077 didClose := make(chan error, 1) 2078 go func() { 2079 didClose <- res.Body.Close() 2080 }() 2081 select { 2082 case err := <-didClose: 2083 if err != nil { 2084 t.Errorf("Close = %v", err) 2085 } 2086 case <-time.After(10 * time.Second): 2087 t.Fatal("too long waiting for close") 2088 } 2089 select { 2090 case err := <-writeErr: 2091 if err == nil { 2092 t.Errorf("expected non-nil write error") 2093 } 2094 case <-time.After(10 * time.Second): 2095 t.Fatal("too long waiting for write error") 2096 } 2097 } 2098 2099 type fooProto struct{} 2100 2101 func (fooProto) RoundTrip(req *Request) (*Response, error) { 2102 res := &Response{ 2103 Status: "200 OK", 2104 StatusCode: 200, 2105 Header: make(Header), 2106 Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())), 2107 } 2108 return res, nil 2109 } 2110 2111 func TestTransportAltProto(t *testing.T) { 2112 defer afterTest(t) 2113 tr := &Transport{} 2114 c := &Client{Transport: tr} 2115 tr.RegisterProtocol("foo", fooProto{}) 2116 res, err := c.Get("foo://bar.com/path") 2117 if err != nil { 2118 t.Fatal(err) 2119 } 2120 bodyb, err := ioutil.ReadAll(res.Body) 2121 if err != nil { 2122 t.Fatal(err) 2123 } 2124 body := string(bodyb) 2125 if e := "You wanted foo://bar.com/path"; body != e { 2126 t.Errorf("got response %q, want %q", body, e) 2127 } 2128 } 2129 2130 func TestTransportNoHost(t *testing.T) { 2131 defer afterTest(t) 2132 tr := &Transport{} 2133 _, err := tr.RoundTrip(&Request{ 2134 Header: make(Header), 2135 URL: &url.URL{ 2136 Scheme: "http", 2137 }, 2138 }) 2139 want := "http: no Host in request URL" 2140 if got := fmt.Sprint(err); got != want { 2141 t.Errorf("error = %v; want %q", err, want) 2142 } 2143 } 2144 2145 // Issue 13311 2146 func TestTransportEmptyMethod(t *testing.T) { 2147 req, _ := NewRequest("GET", "http://foo.com/", nil) 2148 req.Method = "" // docs say "For client requests an empty string means GET" 2149 got, err := httputil.DumpRequestOut(req, false) // DumpRequestOut uses Transport 2150 if err != nil { 2151 t.Fatal(err) 2152 } 2153 if !strings.Contains(string(got), "GET ") { 2154 t.Fatalf("expected substring 'GET '; got: %s", got) 2155 } 2156 } 2157 2158 func TestTransportSocketLateBinding(t *testing.T) { 2159 setParallel(t) 2160 defer afterTest(t) 2161 2162 mux := NewServeMux() 2163 fooGate := make(chan bool, 1) 2164 mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) { 2165 w.Header().Set("foo-ipport", r.RemoteAddr) 2166 w.(Flusher).Flush() 2167 <-fooGate 2168 }) 2169 mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) { 2170 w.Header().Set("bar-ipport", r.RemoteAddr) 2171 }) 2172 ts := httptest.NewServer(mux) 2173 defer ts.Close() 2174 2175 dialGate := make(chan bool, 1) 2176 c := ts.Client() 2177 c.Transport.(*Transport).Dial = func(n, addr string) (net.Conn, error) { 2178 if <-dialGate { 2179 return net.Dial(n, addr) 2180 } 2181 return nil, errors.New("manually closed") 2182 } 2183 2184 dialGate <- true // only allow one dial 2185 fooRes, err := c.Get(ts.URL + "/foo") 2186 if err != nil { 2187 t.Fatal(err) 2188 } 2189 fooAddr := fooRes.Header.Get("foo-ipport") 2190 if fooAddr == "" { 2191 t.Fatal("No addr on /foo request") 2192 } 2193 time.AfterFunc(200*time.Millisecond, func() { 2194 // let the foo response finish so we can use its 2195 // connection for /bar 2196 fooGate <- true 2197 io.Copy(ioutil.Discard, fooRes.Body) 2198 fooRes.Body.Close() 2199 }) 2200 2201 barRes, err := c.Get(ts.URL + "/bar") 2202 if err != nil { 2203 t.Fatal(err) 2204 } 2205 barAddr := barRes.Header.Get("bar-ipport") 2206 if barAddr != fooAddr { 2207 t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr) 2208 } 2209 barRes.Body.Close() 2210 dialGate <- false 2211 } 2212 2213 // Issue 2184 2214 func TestTransportReading100Continue(t *testing.T) { 2215 defer afterTest(t) 2216 2217 const numReqs = 5 2218 reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) } 2219 reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) } 2220 2221 send100Response := func(w *io.PipeWriter, r *io.PipeReader) { 2222 defer w.Close() 2223 defer r.Close() 2224 br := bufio.NewReader(r) 2225 n := 0 2226 for { 2227 n++ 2228 req, err := ReadRequest(br) 2229 if err == io.EOF { 2230 return 2231 } 2232 if err != nil { 2233 t.Error(err) 2234 return 2235 } 2236 slurp, err := ioutil.ReadAll(req.Body) 2237 if err != nil { 2238 t.Errorf("Server request body slurp: %v", err) 2239 return 2240 } 2241 id := req.Header.Get("Request-Id") 2242 resCode := req.Header.Get("X-Want-Response-Code") 2243 if resCode == "" { 2244 resCode = "100 Continue" 2245 if string(slurp) != reqBody(n) { 2246 t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n)) 2247 } 2248 } 2249 body := fmt.Sprintf("Response number %d", n) 2250 v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s 2251 Date: Thu, 28 Feb 2013 17:55:41 GMT 2252 2253 HTTP/1.1 200 OK 2254 Content-Type: text/html 2255 Echo-Request-Id: %s 2256 Content-Length: %d 2257 2258 %s`, resCode, id, len(body), body), "\n", "\r\n", -1)) 2259 w.Write(v) 2260 if id == reqID(numReqs) { 2261 return 2262 } 2263 } 2264 2265 } 2266 2267 tr := &Transport{ 2268 Dial: func(n, addr string) (net.Conn, error) { 2269 sr, sw := io.Pipe() // server read/write 2270 cr, cw := io.Pipe() // client read/write 2271 conn := &rwTestConn{ 2272 Reader: cr, 2273 Writer: sw, 2274 closeFunc: func() error { 2275 sw.Close() 2276 cw.Close() 2277 return nil 2278 }, 2279 } 2280 go send100Response(cw, sr) 2281 return conn, nil 2282 }, 2283 DisableKeepAlives: false, 2284 } 2285 defer tr.CloseIdleConnections() 2286 c := &Client{Transport: tr} 2287 2288 testResponse := func(req *Request, name string, wantCode int) { 2289 res, err := c.Do(req) 2290 if err != nil { 2291 t.Fatalf("%s: Do: %v", name, err) 2292 } 2293 if res.StatusCode != wantCode { 2294 t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode) 2295 } 2296 if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack { 2297 t.Errorf("%s: response id %q != request id %q", name, idBack, id) 2298 } 2299 _, err = ioutil.ReadAll(res.Body) 2300 if err != nil { 2301 t.Fatalf("%s: Slurp error: %v", name, err) 2302 } 2303 } 2304 2305 // Few 100 responses, making sure we're not off-by-one. 2306 for i := 1; i <= numReqs; i++ { 2307 req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i))) 2308 req.Header.Set("Request-Id", reqID(i)) 2309 testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200) 2310 } 2311 2312 // And some other informational 1xx but non-100 responses, to test 2313 // we return them but don't re-use the connection. 2314 for i := 1; i <= numReqs; i++ { 2315 req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i))) 2316 req.Header.Set("X-Want-Response-Code", "123 Sesame Street") 2317 testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123) 2318 } 2319 } 2320 2321 type proxyFromEnvTest struct { 2322 req string // URL to fetch; blank means "http://example.com" 2323 2324 env string // HTTP_PROXY 2325 httpsenv string // HTTPS_PROXY 2326 noenv string // NO_PROXY 2327 reqmeth string // REQUEST_METHOD 2328 2329 want string 2330 wanterr error 2331 } 2332 2333 func (t proxyFromEnvTest) String() string { 2334 var buf bytes.Buffer 2335 space := func() { 2336 if buf.Len() > 0 { 2337 buf.WriteByte(' ') 2338 } 2339 } 2340 if t.env != "" { 2341 fmt.Fprintf(&buf, "http_proxy=%q", t.env) 2342 } 2343 if t.httpsenv != "" { 2344 space() 2345 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv) 2346 } 2347 if t.noenv != "" { 2348 space() 2349 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv) 2350 } 2351 if t.reqmeth != "" { 2352 space() 2353 fmt.Fprintf(&buf, "request_method=%q", t.reqmeth) 2354 } 2355 req := "http://example.com" 2356 if t.req != "" { 2357 req = t.req 2358 } 2359 space() 2360 fmt.Fprintf(&buf, "req=%q", req) 2361 return strings.TrimSpace(buf.String()) 2362 } 2363 2364 var proxyFromEnvTests = []proxyFromEnvTest{ 2365 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2366 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"}, 2367 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"}, 2368 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"}, 2369 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 2370 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"}, 2371 {env: "socks5://127.0.0.1", want: "socks5://127.0.0.1"}, 2372 2373 // Don't use secure for http 2374 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"}, 2375 // Use secure for https. 2376 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"}, 2377 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"}, 2378 2379 // Issue 16405: don't use HTTP_PROXY in a CGI environment, 2380 // where HTTP_PROXY can be attacker-controlled. 2381 {env: "http://10.1.2.3:8080", reqmeth: "POST", 2382 want: "<nil>", 2383 wanterr: errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")}, 2384 2385 {want: "<nil>"}, 2386 2387 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2388 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 2389 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2390 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"}, 2391 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 2392 } 2393 2394 func TestProxyFromEnvironment(t *testing.T) { 2395 ResetProxyEnv() 2396 defer ResetProxyEnv() 2397 for _, tt := range proxyFromEnvTests { 2398 os.Setenv("HTTP_PROXY", tt.env) 2399 os.Setenv("HTTPS_PROXY", tt.httpsenv) 2400 os.Setenv("NO_PROXY", tt.noenv) 2401 os.Setenv("REQUEST_METHOD", tt.reqmeth) 2402 ResetCachedEnvironment() 2403 reqURL := tt.req 2404 if reqURL == "" { 2405 reqURL = "http://example.com" 2406 } 2407 req, _ := NewRequest("GET", reqURL, nil) 2408 url, err := ProxyFromEnvironment(req) 2409 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 2410 t.Errorf("%v: got error = %q, want %q", tt, g, e) 2411 continue 2412 } 2413 if got := fmt.Sprintf("%s", url); got != tt.want { 2414 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 2415 } 2416 } 2417 } 2418 2419 func TestIdleConnChannelLeak(t *testing.T) { 2420 // Not parallel: uses global test hooks. 2421 var mu sync.Mutex 2422 var n int 2423 2424 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2425 mu.Lock() 2426 n++ 2427 mu.Unlock() 2428 })) 2429 defer ts.Close() 2430 2431 const nReqs = 5 2432 didRead := make(chan bool, nReqs) 2433 SetReadLoopBeforeNextReadHook(func() { didRead <- true }) 2434 defer SetReadLoopBeforeNextReadHook(nil) 2435 2436 c := ts.Client() 2437 tr := c.Transport.(*Transport) 2438 tr.Dial = func(netw, addr string) (net.Conn, error) { 2439 return net.Dial(netw, ts.Listener.Addr().String()) 2440 } 2441 2442 // First, without keep-alives. 2443 for _, disableKeep := range []bool{true, false} { 2444 tr.DisableKeepAlives = disableKeep 2445 for i := 0; i < nReqs; i++ { 2446 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i)) 2447 if err != nil { 2448 t.Fatal(err) 2449 } 2450 // Note: no res.Body.Close is needed here, since the 2451 // response Content-Length is zero. Perhaps the test 2452 // should be more explicit and use a HEAD, but tests 2453 // elsewhere guarantee that zero byte responses generate 2454 // a "Content-Length: 0" instead of chunking. 2455 } 2456 2457 // At this point, each of the 5 Transport.readLoop goroutines 2458 // are scheduling noting that there are no response bodies (see 2459 // earlier comment), and are then calling putIdleConn, which 2460 // decrements this count. Usually that happens quickly, which is 2461 // why this test has seemed to work for ages. But it's still 2462 // racey: we have wait for them to finish first. See Issue 10427 2463 for i := 0; i < nReqs; i++ { 2464 <-didRead 2465 } 2466 2467 if got := tr.IdleConnChMapSizeForTesting(); got != 0 { 2468 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got) 2469 } 2470 } 2471 } 2472 2473 // Verify the status quo: that the Client.Post function coerces its 2474 // body into a ReadCloser if it's a Closer, and that the Transport 2475 // then closes it. 2476 func TestTransportClosesRequestBody(t *testing.T) { 2477 defer afterTest(t) 2478 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2479 io.Copy(ioutil.Discard, r.Body) 2480 })) 2481 defer ts.Close() 2482 2483 c := ts.Client() 2484 2485 closes := 0 2486 2487 res, err := c.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")}) 2488 if err != nil { 2489 t.Fatal(err) 2490 } 2491 res.Body.Close() 2492 if closes != 1 { 2493 t.Errorf("closes = %d; want 1", closes) 2494 } 2495 } 2496 2497 func TestTransportTLSHandshakeTimeout(t *testing.T) { 2498 defer afterTest(t) 2499 if testing.Short() { 2500 t.Skip("skipping in short mode") 2501 } 2502 ln := newLocalListener(t) 2503 defer ln.Close() 2504 testdonec := make(chan struct{}) 2505 defer close(testdonec) 2506 2507 go func() { 2508 c, err := ln.Accept() 2509 if err != nil { 2510 t.Error(err) 2511 return 2512 } 2513 <-testdonec 2514 c.Close() 2515 }() 2516 2517 getdonec := make(chan struct{}) 2518 go func() { 2519 defer close(getdonec) 2520 tr := &Transport{ 2521 Dial: func(_, _ string) (net.Conn, error) { 2522 return net.Dial("tcp", ln.Addr().String()) 2523 }, 2524 TLSHandshakeTimeout: 250 * time.Millisecond, 2525 } 2526 cl := &Client{Transport: tr} 2527 _, err := cl.Get("https://dummy.tld/") 2528 if err == nil { 2529 t.Error("expected error") 2530 return 2531 } 2532 ue, ok := err.(*url.Error) 2533 if !ok { 2534 t.Errorf("expected url.Error; got %#v", err) 2535 return 2536 } 2537 ne, ok := ue.Err.(net.Error) 2538 if !ok { 2539 t.Errorf("expected net.Error; got %#v", err) 2540 return 2541 } 2542 if !ne.Timeout() { 2543 t.Errorf("expected timeout error; got %v", err) 2544 } 2545 if !strings.Contains(err.Error(), "handshake timeout") { 2546 t.Errorf("expected 'handshake timeout' in error; got %v", err) 2547 } 2548 }() 2549 select { 2550 case <-getdonec: 2551 case <-time.After(5 * time.Second): 2552 t.Error("test timeout; TLS handshake hung?") 2553 } 2554 } 2555 2556 // Trying to repro golang.org/issue/3514 2557 func TestTLSServerClosesConnection(t *testing.T) { 2558 defer afterTest(t) 2559 testenv.SkipFlaky(t, 7634) 2560 2561 closedc := make(chan bool, 1) 2562 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2563 if strings.Contains(r.URL.Path, "/keep-alive-then-die") { 2564 conn, _, _ := w.(Hijacker).Hijack() 2565 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) 2566 conn.Close() 2567 closedc <- true 2568 return 2569 } 2570 fmt.Fprintf(w, "hello") 2571 })) 2572 defer ts.Close() 2573 2574 c := ts.Client() 2575 tr := c.Transport.(*Transport) 2576 2577 var nSuccess = 0 2578 var errs []error 2579 const trials = 20 2580 for i := 0; i < trials; i++ { 2581 tr.CloseIdleConnections() 2582 res, err := c.Get(ts.URL + "/keep-alive-then-die") 2583 if err != nil { 2584 t.Fatal(err) 2585 } 2586 <-closedc 2587 slurp, err := ioutil.ReadAll(res.Body) 2588 if err != nil { 2589 t.Fatal(err) 2590 } 2591 if string(slurp) != "foo" { 2592 t.Errorf("Got %q, want foo", slurp) 2593 } 2594 2595 // Now try again and see if we successfully 2596 // pick a new connection. 2597 res, err = c.Get(ts.URL + "/") 2598 if err != nil { 2599 errs = append(errs, err) 2600 continue 2601 } 2602 slurp, err = ioutil.ReadAll(res.Body) 2603 if err != nil { 2604 errs = append(errs, err) 2605 continue 2606 } 2607 nSuccess++ 2608 } 2609 if nSuccess > 0 { 2610 t.Logf("successes = %d of %d", nSuccess, trials) 2611 } else { 2612 t.Errorf("All runs failed:") 2613 } 2614 for _, err := range errs { 2615 t.Logf(" err: %v", err) 2616 } 2617 } 2618 2619 // byteFromChanReader is an io.Reader that reads a single byte at a 2620 // time from the channel. When the channel is closed, the reader 2621 // returns io.EOF. 2622 type byteFromChanReader chan byte 2623 2624 func (c byteFromChanReader) Read(p []byte) (n int, err error) { 2625 if len(p) == 0 { 2626 return 2627 } 2628 b, ok := <-c 2629 if !ok { 2630 return 0, io.EOF 2631 } 2632 p[0] = b 2633 return 1, nil 2634 } 2635 2636 // Verifies that the Transport doesn't reuse a connection in the case 2637 // where the server replies before the request has been fully 2638 // written. We still honor that reply (see TestIssue3595), but don't 2639 // send future requests on the connection because it's then in a 2640 // questionable state. 2641 // golang.org/issue/7569 2642 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) { 2643 setParallel(t) 2644 defer afterTest(t) 2645 var sconn struct { 2646 sync.Mutex 2647 c net.Conn 2648 } 2649 var getOkay bool 2650 closeConn := func() { 2651 sconn.Lock() 2652 defer sconn.Unlock() 2653 if sconn.c != nil { 2654 sconn.c.Close() 2655 sconn.c = nil 2656 if !getOkay { 2657 t.Logf("Closed server connection") 2658 } 2659 } 2660 } 2661 defer closeConn() 2662 2663 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2664 if r.Method == "GET" { 2665 io.WriteString(w, "bar") 2666 return 2667 } 2668 conn, _, _ := w.(Hijacker).Hijack() 2669 sconn.Lock() 2670 sconn.c = conn 2671 sconn.Unlock() 2672 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive 2673 go io.Copy(ioutil.Discard, conn) 2674 })) 2675 defer ts.Close() 2676 c := ts.Client() 2677 2678 const bodySize = 256 << 10 2679 finalBit := make(byteFromChanReader, 1) 2680 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit)) 2681 req.ContentLength = bodySize 2682 res, err := c.Do(req) 2683 if err := wantBody(res, err, "foo"); err != nil { 2684 t.Errorf("POST response: %v", err) 2685 } 2686 donec := make(chan bool) 2687 go func() { 2688 defer close(donec) 2689 res, err = c.Get(ts.URL) 2690 if err := wantBody(res, err, "bar"); err != nil { 2691 t.Errorf("GET response: %v", err) 2692 return 2693 } 2694 getOkay = true // suppress test noise 2695 }() 2696 time.AfterFunc(5*time.Second, closeConn) 2697 select { 2698 case <-donec: 2699 finalBit <- 'x' // unblock the writeloop of the first Post 2700 close(finalBit) 2701 case <-time.After(7 * time.Second): 2702 t.Fatal("timeout waiting for GET request to finish") 2703 } 2704 } 2705 2706 // Tests that we don't leak Transport persistConn.readLoop goroutines 2707 // when a server hangs up immediately after saying it would keep-alive. 2708 func TestTransportIssue10457(t *testing.T) { 2709 defer afterTest(t) // used to fail in goroutine leak check 2710 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2711 // Send a response with no body, keep-alive 2712 // (implicit), and then lie and immediately close the 2713 // connection. This forces the Transport's readLoop to 2714 // immediately Peek an io.EOF and get to the point 2715 // that used to hang. 2716 conn, _, _ := w.(Hijacker).Hijack() 2717 conn.Write([]byte("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 0\r\n\r\n")) // keep-alive 2718 conn.Close() 2719 })) 2720 defer ts.Close() 2721 c := ts.Client() 2722 2723 res, err := c.Get(ts.URL) 2724 if err != nil { 2725 t.Fatalf("Get: %v", err) 2726 } 2727 defer res.Body.Close() 2728 2729 // Just a sanity check that we at least get the response. The real 2730 // test here is that the "defer afterTest" above doesn't find any 2731 // leaked goroutines. 2732 if got, want := res.Header.Get("Foo"), "Bar"; got != want { 2733 t.Errorf("Foo header = %q; want %q", got, want) 2734 } 2735 } 2736 2737 type errorReader struct { 2738 err error 2739 } 2740 2741 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err } 2742 2743 type closerFunc func() error 2744 2745 func (f closerFunc) Close() error { return f() } 2746 2747 type writerFuncConn struct { 2748 net.Conn 2749 write func(p []byte) (n int, err error) 2750 } 2751 2752 func (c writerFuncConn) Write(p []byte) (n int, err error) { return c.write(p) } 2753 2754 // Issues 4677, 18241, and 17844. If we try to reuse a connection that the 2755 // server is in the process of closing, we may end up successfully writing out 2756 // our request (or a portion of our request) only to find a connection error 2757 // when we try to read from (or finish writing to) the socket. 2758 // 2759 // NOTE: we resend a request only if: 2760 // - we reused a keep-alive connection 2761 // - we haven't yet received any header data 2762 // - either we wrote no bytes to the server, or the request is idempotent 2763 // This automatically prevents an infinite resend loop because we'll run out of 2764 // the cached keep-alive connections eventually. 2765 func TestRetryRequestsOnError(t *testing.T) { 2766 newRequest := func(method, urlStr string, body io.Reader) *Request { 2767 req, err := NewRequest(method, urlStr, body) 2768 if err != nil { 2769 t.Fatal(err) 2770 } 2771 return req 2772 } 2773 2774 testCases := []struct { 2775 name string 2776 failureN int 2777 failureErr error 2778 // Note that we can't just re-use the Request object across calls to c.Do 2779 // because we need to rewind Body between calls. (GetBody is only used to 2780 // rewind Body on failure and redirects, not just because it's done.) 2781 req func() *Request 2782 reqString string 2783 }{ 2784 { 2785 name: "IdempotentNoBodySomeWritten", 2786 // Believe that we've written some bytes to the server, so we know we're 2787 // not just in the "retry when no bytes sent" case". 2788 failureN: 1, 2789 // Use the specific error that shouldRetryRequest looks for with idempotent requests. 2790 failureErr: ExportErrServerClosedIdle, 2791 req: func() *Request { 2792 return newRequest("GET", "http://fake.golang", nil) 2793 }, 2794 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`, 2795 }, 2796 { 2797 name: "IdempotentGetBodySomeWritten", 2798 // Believe that we've written some bytes to the server, so we know we're 2799 // not just in the "retry when no bytes sent" case". 2800 failureN: 1, 2801 // Use the specific error that shouldRetryRequest looks for with idempotent requests. 2802 failureErr: ExportErrServerClosedIdle, 2803 req: func() *Request { 2804 return newRequest("GET", "http://fake.golang", strings.NewReader("foo\n")) 2805 }, 2806 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`, 2807 }, 2808 { 2809 name: "NothingWrittenNoBody", 2810 // It's key that we return 0 here -- that's what enables Transport to know 2811 // that nothing was written, even though this is a non-idempotent request. 2812 failureN: 0, 2813 failureErr: errors.New("second write fails"), 2814 req: func() *Request { 2815 return newRequest("DELETE", "http://fake.golang", nil) 2816 }, 2817 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`, 2818 }, 2819 { 2820 name: "NothingWrittenGetBody", 2821 // It's key that we return 0 here -- that's what enables Transport to know 2822 // that nothing was written, even though this is a non-idempotent request. 2823 failureN: 0, 2824 failureErr: errors.New("second write fails"), 2825 // Note that NewRequest will set up GetBody for strings.Reader, which is 2826 // required for the retry to occur 2827 req: func() *Request { 2828 return newRequest("POST", "http://fake.golang", strings.NewReader("foo\n")) 2829 }, 2830 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`, 2831 }, 2832 } 2833 2834 for _, tc := range testCases { 2835 t.Run(tc.name, func(t *testing.T) { 2836 defer afterTest(t) 2837 2838 var ( 2839 mu sync.Mutex 2840 logbuf bytes.Buffer 2841 ) 2842 logf := func(format string, args ...interface{}) { 2843 mu.Lock() 2844 defer mu.Unlock() 2845 fmt.Fprintf(&logbuf, format, args...) 2846 logbuf.WriteByte('\n') 2847 } 2848 2849 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2850 logf("Handler") 2851 w.Header().Set("X-Status", "ok") 2852 })) 2853 defer ts.Close() 2854 2855 var writeNumAtomic int32 2856 c := ts.Client() 2857 c.Transport.(*Transport).Dial = func(network, addr string) (net.Conn, error) { 2858 logf("Dial") 2859 c, err := net.Dial(network, ts.Listener.Addr().String()) 2860 if err != nil { 2861 logf("Dial error: %v", err) 2862 return nil, err 2863 } 2864 return &writerFuncConn{ 2865 Conn: c, 2866 write: func(p []byte) (n int, err error) { 2867 if atomic.AddInt32(&writeNumAtomic, 1) == 2 { 2868 logf("intentional write failure") 2869 return tc.failureN, tc.failureErr 2870 } 2871 logf("Write(%q)", p) 2872 return c.Write(p) 2873 }, 2874 }, nil 2875 } 2876 2877 SetRoundTripRetried(func() { 2878 logf("Retried.") 2879 }) 2880 defer SetRoundTripRetried(nil) 2881 2882 for i := 0; i < 3; i++ { 2883 res, err := c.Do(tc.req()) 2884 if err != nil { 2885 t.Fatalf("i=%d: Do = %v", i, err) 2886 } 2887 res.Body.Close() 2888 } 2889 2890 mu.Lock() 2891 got := logbuf.String() 2892 mu.Unlock() 2893 want := fmt.Sprintf(`Dial 2894 Write("%s") 2895 Handler 2896 intentional write failure 2897 Retried. 2898 Dial 2899 Write("%s") 2900 Handler 2901 Write("%s") 2902 Handler 2903 `, tc.reqString, tc.reqString, tc.reqString) 2904 if got != want { 2905 t.Errorf("Log of events differs. Got:\n%s\nWant:\n%s", got, want) 2906 } 2907 }) 2908 } 2909 } 2910 2911 // Issue 6981 2912 func TestTransportClosesBodyOnError(t *testing.T) { 2913 setParallel(t) 2914 defer afterTest(t) 2915 readBody := make(chan error, 1) 2916 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2917 _, err := ioutil.ReadAll(r.Body) 2918 readBody <- err 2919 })) 2920 defer ts.Close() 2921 c := ts.Client() 2922 fakeErr := errors.New("fake error") 2923 didClose := make(chan bool, 1) 2924 req, _ := NewRequest("POST", ts.URL, struct { 2925 io.Reader 2926 io.Closer 2927 }{ 2928 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}), 2929 closerFunc(func() error { 2930 select { 2931 case didClose <- true: 2932 default: 2933 } 2934 return nil 2935 }), 2936 }) 2937 res, err := c.Do(req) 2938 if res != nil { 2939 defer res.Body.Close() 2940 } 2941 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 2942 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 2943 } 2944 select { 2945 case err := <-readBody: 2946 if err == nil { 2947 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 2948 } 2949 case <-time.After(5 * time.Second): 2950 t.Error("timeout waiting for server handler to complete") 2951 } 2952 select { 2953 case <-didClose: 2954 default: 2955 t.Errorf("didn't see Body.Close") 2956 } 2957 } 2958 2959 func TestTransportDialTLS(t *testing.T) { 2960 setParallel(t) 2961 defer afterTest(t) 2962 var mu sync.Mutex // guards following 2963 var gotReq, didDial bool 2964 2965 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2966 mu.Lock() 2967 gotReq = true 2968 mu.Unlock() 2969 })) 2970 defer ts.Close() 2971 c := ts.Client() 2972 c.Transport.(*Transport).DialTLS = func(netw, addr string) (net.Conn, error) { 2973 mu.Lock() 2974 didDial = true 2975 mu.Unlock() 2976 c, err := tls.Dial(netw, addr, c.Transport.(*Transport).TLSClientConfig) 2977 if err != nil { 2978 return nil, err 2979 } 2980 return c, c.Handshake() 2981 } 2982 2983 res, err := c.Get(ts.URL) 2984 if err != nil { 2985 t.Fatal(err) 2986 } 2987 res.Body.Close() 2988 mu.Lock() 2989 if !gotReq { 2990 t.Error("didn't get request") 2991 } 2992 if !didDial { 2993 t.Error("didn't use dial hook") 2994 } 2995 } 2996 2997 // Test for issue 8755 2998 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 2999 func TestRoundTripReturnsProxyError(t *testing.T) { 3000 badProxy := func(*Request) (*url.URL, error) { 3001 return nil, errors.New("errorMessage") 3002 } 3003 3004 tr := &Transport{Proxy: badProxy} 3005 3006 req, _ := NewRequest("GET", "http://example.com", nil) 3007 3008 _, err := tr.RoundTrip(req) 3009 3010 if err == nil { 3011 t.Error("Expected proxy error to be returned by RoundTrip") 3012 } 3013 } 3014 3015 // tests that putting an idle conn after a call to CloseIdleConns does return it 3016 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 3017 tr := &Transport{} 3018 wantIdle := func(when string, n int) bool { 3019 got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn 3020 if got == n { 3021 return true 3022 } 3023 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 3024 return false 3025 } 3026 wantIdle("start", 0) 3027 if !tr.PutIdleTestConn() { 3028 t.Fatal("put failed") 3029 } 3030 if !tr.PutIdleTestConn() { 3031 t.Fatal("second put failed") 3032 } 3033 wantIdle("after put", 2) 3034 tr.CloseIdleConnections() 3035 if !tr.IsIdleForTesting() { 3036 t.Error("should be idle after CloseIdleConnections") 3037 } 3038 wantIdle("after close idle", 0) 3039 if tr.PutIdleTestConn() { 3040 t.Fatal("put didn't fail") 3041 } 3042 wantIdle("after second put", 0) 3043 3044 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode 3045 if tr.IsIdleForTesting() { 3046 t.Error("shouldn't be idle after RequestIdleConnChForTesting") 3047 } 3048 if !tr.PutIdleTestConn() { 3049 t.Fatal("after re-activation") 3050 } 3051 wantIdle("after final put", 1) 3052 } 3053 3054 // This tests that an client requesting a content range won't also 3055 // implicitly ask for gzip support. If they want that, they need to do it 3056 // on their own. 3057 // golang.org/issue/8923 3058 func TestTransportRangeAndGzip(t *testing.T) { 3059 defer afterTest(t) 3060 reqc := make(chan *Request, 1) 3061 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3062 reqc <- r 3063 })) 3064 defer ts.Close() 3065 c := ts.Client() 3066 3067 req, _ := NewRequest("GET", ts.URL, nil) 3068 req.Header.Set("Range", "bytes=7-11") 3069 res, err := c.Do(req) 3070 if err != nil { 3071 t.Fatal(err) 3072 } 3073 3074 select { 3075 case r := <-reqc: 3076 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 3077 t.Error("Transport advertised gzip support in the Accept header") 3078 } 3079 if r.Header.Get("Range") == "" { 3080 t.Error("no Range in request") 3081 } 3082 case <-time.After(10 * time.Second): 3083 t.Fatal("timeout") 3084 } 3085 res.Body.Close() 3086 } 3087 3088 // Test for issue 10474 3089 func TestTransportResponseCancelRace(t *testing.T) { 3090 defer afterTest(t) 3091 3092 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3093 // important that this response has a body. 3094 var b [1024]byte 3095 w.Write(b[:]) 3096 })) 3097 defer ts.Close() 3098 tr := ts.Client().Transport.(*Transport) 3099 3100 req, err := NewRequest("GET", ts.URL, nil) 3101 if err != nil { 3102 t.Fatal(err) 3103 } 3104 res, err := tr.RoundTrip(req) 3105 if err != nil { 3106 t.Fatal(err) 3107 } 3108 // If we do an early close, Transport just throws the connection away and 3109 // doesn't reuse it. In order to trigger the bug, it has to reuse the connection 3110 // so read the body 3111 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { 3112 t.Fatal(err) 3113 } 3114 3115 req2, err := NewRequest("GET", ts.URL, nil) 3116 if err != nil { 3117 t.Fatal(err) 3118 } 3119 tr.CancelRequest(req) 3120 res, err = tr.RoundTrip(req2) 3121 if err != nil { 3122 t.Fatal(err) 3123 } 3124 res.Body.Close() 3125 } 3126 3127 // Test for issue 19248: Content-Encoding's value is case insensitive. 3128 func TestTransportContentEncodingCaseInsensitive(t *testing.T) { 3129 setParallel(t) 3130 defer afterTest(t) 3131 for _, ce := range []string{"gzip", "GZIP"} { 3132 ce := ce 3133 t.Run(ce, func(t *testing.T) { 3134 const encodedString = "Hello Gopher" 3135 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3136 w.Header().Set("Content-Encoding", ce) 3137 gz := gzip.NewWriter(w) 3138 gz.Write([]byte(encodedString)) 3139 gz.Close() 3140 })) 3141 defer ts.Close() 3142 3143 res, err := ts.Client().Get(ts.URL) 3144 if err != nil { 3145 t.Fatal(err) 3146 } 3147 3148 body, err := ioutil.ReadAll(res.Body) 3149 res.Body.Close() 3150 if err != nil { 3151 t.Fatal(err) 3152 } 3153 3154 if string(body) != encodedString { 3155 t.Fatalf("Expected body %q, got: %q\n", encodedString, string(body)) 3156 } 3157 }) 3158 } 3159 } 3160 3161 func TestTransportDialCancelRace(t *testing.T) { 3162 defer afterTest(t) 3163 3164 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 3165 defer ts.Close() 3166 tr := ts.Client().Transport.(*Transport) 3167 3168 req, err := NewRequest("GET", ts.URL, nil) 3169 if err != nil { 3170 t.Fatal(err) 3171 } 3172 SetEnterRoundTripHook(func() { 3173 tr.CancelRequest(req) 3174 }) 3175 defer SetEnterRoundTripHook(nil) 3176 res, err := tr.RoundTrip(req) 3177 if err != ExportErrRequestCanceled { 3178 t.Errorf("expected canceled request error; got %v", err) 3179 if err == nil { 3180 res.Body.Close() 3181 } 3182 } 3183 } 3184 3185 // logWritesConn is a net.Conn that logs each Write call to writes 3186 // and then proxies to w. 3187 // It proxies Read calls to a reader it receives from rch. 3188 type logWritesConn struct { 3189 net.Conn // nil. crash on use. 3190 3191 w io.Writer 3192 3193 rch <-chan io.Reader 3194 r io.Reader // nil until received by rch 3195 3196 mu sync.Mutex 3197 writes []string 3198 } 3199 3200 func (c *logWritesConn) Write(p []byte) (n int, err error) { 3201 c.mu.Lock() 3202 defer c.mu.Unlock() 3203 c.writes = append(c.writes, string(p)) 3204 return c.w.Write(p) 3205 } 3206 3207 func (c *logWritesConn) Read(p []byte) (n int, err error) { 3208 if c.r == nil { 3209 c.r = <-c.rch 3210 } 3211 return c.r.Read(p) 3212 } 3213 3214 func (c *logWritesConn) Close() error { return nil } 3215 3216 // Issue 6574 3217 func TestTransportFlushesBodyChunks(t *testing.T) { 3218 defer afterTest(t) 3219 resBody := make(chan io.Reader, 1) 3220 connr, connw := io.Pipe() // connection pipe pair 3221 lw := &logWritesConn{ 3222 rch: resBody, 3223 w: connw, 3224 } 3225 tr := &Transport{ 3226 Dial: func(network, addr string) (net.Conn, error) { 3227 return lw, nil 3228 }, 3229 } 3230 bodyr, bodyw := io.Pipe() // body pipe pair 3231 go func() { 3232 defer bodyw.Close() 3233 for i := 0; i < 3; i++ { 3234 fmt.Fprintf(bodyw, "num%d\n", i) 3235 } 3236 }() 3237 resc := make(chan *Response) 3238 go func() { 3239 req, _ := NewRequest("POST", "http://localhost:8080", bodyr) 3240 req.Header.Set("User-Agent", "x") // known value for test 3241 res, err := tr.RoundTrip(req) 3242 if err != nil { 3243 t.Errorf("RoundTrip: %v", err) 3244 close(resc) 3245 return 3246 } 3247 resc <- res 3248 3249 }() 3250 // Fully consume the request before checking the Write log vs. want. 3251 req, err := ReadRequest(bufio.NewReader(connr)) 3252 if err != nil { 3253 t.Fatal(err) 3254 } 3255 io.Copy(ioutil.Discard, req.Body) 3256 3257 // Unblock the transport's roundTrip goroutine. 3258 resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n") 3259 res, ok := <-resc 3260 if !ok { 3261 return 3262 } 3263 defer res.Body.Close() 3264 3265 want := []string{ 3266 "POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n" + 3267 "5\r\nnum0\n\r\n", 3268 "5\r\nnum1\n\r\n", 3269 "5\r\nnum2\n\r\n", 3270 "0\r\n\r\n", 3271 } 3272 if !reflect.DeepEqual(lw.writes, want) { 3273 t.Errorf("Writes differed.\n Got: %q\nWant: %q\n", lw.writes, want) 3274 } 3275 } 3276 3277 // Issue 11745. 3278 func TestTransportPrefersResponseOverWriteError(t *testing.T) { 3279 if testing.Short() { 3280 t.Skip("skipping in short mode") 3281 } 3282 defer afterTest(t) 3283 const contentLengthLimit = 1024 * 1024 // 1MB 3284 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3285 if r.ContentLength >= contentLengthLimit { 3286 w.WriteHeader(StatusBadRequest) 3287 r.Body.Close() 3288 return 3289 } 3290 w.WriteHeader(StatusOK) 3291 })) 3292 defer ts.Close() 3293 c := ts.Client() 3294 3295 fail := 0 3296 count := 100 3297 bigBody := strings.Repeat("a", contentLengthLimit*2) 3298 for i := 0; i < count; i++ { 3299 req, err := NewRequest("PUT", ts.URL, strings.NewReader(bigBody)) 3300 if err != nil { 3301 t.Fatal(err) 3302 } 3303 resp, err := c.Do(req) 3304 if err != nil { 3305 fail++ 3306 t.Logf("%d = %#v", i, err) 3307 if ue, ok := err.(*url.Error); ok { 3308 t.Logf("urlErr = %#v", ue.Err) 3309 if ne, ok := ue.Err.(*net.OpError); ok { 3310 t.Logf("netOpError = %#v", ne.Err) 3311 } 3312 } 3313 } else { 3314 resp.Body.Close() 3315 if resp.StatusCode != 400 { 3316 t.Errorf("Expected status code 400, got %v", resp.Status) 3317 } 3318 } 3319 } 3320 if fail > 0 { 3321 t.Errorf("Failed %v out of %v\n", fail, count) 3322 } 3323 } 3324 3325 func TestTransportAutomaticHTTP2(t *testing.T) { 3326 testTransportAutoHTTP(t, &Transport{}, true) 3327 } 3328 3329 // golang.org/issue/14391: also check DefaultTransport 3330 func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) { 3331 testTransportAutoHTTP(t, DefaultTransport.(*Transport), true) 3332 } 3333 3334 func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { 3335 testTransportAutoHTTP(t, &Transport{ 3336 TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), 3337 }, false) 3338 } 3339 3340 func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { 3341 testTransportAutoHTTP(t, &Transport{ 3342 TLSClientConfig: new(tls.Config), 3343 }, false) 3344 } 3345 3346 func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { 3347 testTransportAutoHTTP(t, &Transport{ 3348 ExpectContinueTimeout: 1 * time.Second, 3349 }, true) 3350 } 3351 3352 func TestTransportAutomaticHTTP2_Dial(t *testing.T) { 3353 var d net.Dialer 3354 testTransportAutoHTTP(t, &Transport{ 3355 Dial: d.Dial, 3356 }, false) 3357 } 3358 3359 func TestTransportAutomaticHTTP2_DialTLS(t *testing.T) { 3360 testTransportAutoHTTP(t, &Transport{ 3361 DialTLS: func(network, addr string) (net.Conn, error) { 3362 panic("unused") 3363 }, 3364 }, false) 3365 } 3366 3367 func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { 3368 _, err := tr.RoundTrip(new(Request)) 3369 if err == nil { 3370 t.Error("expected error from RoundTrip") 3371 } 3372 if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { 3373 t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) 3374 } 3375 } 3376 3377 // Issue 13633: there was a race where we returned bodyless responses 3378 // to callers before recycling the persistent connection, which meant 3379 // a client doing two subsequent requests could end up on different 3380 // connections. It's somewhat harmless but enough tests assume it's 3381 // not true in order to test other things that it's worth fixing. 3382 // Plus it's nice to be consistent and not have timing-dependent 3383 // behavior. 3384 func TestTransportReuseConnEmptyResponseBody(t *testing.T) { 3385 defer afterTest(t) 3386 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3387 w.Header().Set("X-Addr", r.RemoteAddr) 3388 // Empty response body. 3389 })) 3390 defer cst.close() 3391 n := 100 3392 if testing.Short() { 3393 n = 10 3394 } 3395 var firstAddr string 3396 for i := 0; i < n; i++ { 3397 res, err := cst.c.Get(cst.ts.URL) 3398 if err != nil { 3399 log.Fatal(err) 3400 } 3401 addr := res.Header.Get("X-Addr") 3402 if i == 0 { 3403 firstAddr = addr 3404 } else if addr != firstAddr { 3405 t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr) 3406 } 3407 res.Body.Close() 3408 } 3409 } 3410 3411 // Issue 13839 3412 func TestNoCrashReturningTransportAltConn(t *testing.T) { 3413 cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) 3414 if err != nil { 3415 t.Fatal(err) 3416 } 3417 ln := newLocalListener(t) 3418 defer ln.Close() 3419 3420 handledPendingDial := make(chan bool, 1) 3421 SetPendingDialHooks(nil, func() { handledPendingDial <- true }) 3422 defer SetPendingDialHooks(nil, nil) 3423 3424 testDone := make(chan struct{}) 3425 defer close(testDone) 3426 go func() { 3427 tln := tls.NewListener(ln, &tls.Config{ 3428 NextProtos: []string{"foo"}, 3429 Certificates: []tls.Certificate{cert}, 3430 }) 3431 sc, err := tln.Accept() 3432 if err != nil { 3433 t.Error(err) 3434 return 3435 } 3436 if err := sc.(*tls.Conn).Handshake(); err != nil { 3437 t.Error(err) 3438 return 3439 } 3440 <-testDone 3441 sc.Close() 3442 }() 3443 3444 addr := ln.Addr().String() 3445 3446 req, _ := NewRequest("GET", "https://fake.tld/", nil) 3447 cancel := make(chan struct{}) 3448 req.Cancel = cancel 3449 3450 doReturned := make(chan bool, 1) 3451 madeRoundTripper := make(chan bool, 1) 3452 3453 tr := &Transport{ 3454 DisableKeepAlives: true, 3455 TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{ 3456 "foo": func(authority string, c *tls.Conn) RoundTripper { 3457 madeRoundTripper <- true 3458 return funcRoundTripper(func() { 3459 t.Error("foo RoundTripper should not be called") 3460 }) 3461 }, 3462 }, 3463 Dial: func(_, _ string) (net.Conn, error) { 3464 panic("shouldn't be called") 3465 }, 3466 DialTLS: func(_, _ string) (net.Conn, error) { 3467 tc, err := tls.Dial("tcp", addr, &tls.Config{ 3468 InsecureSkipVerify: true, 3469 NextProtos: []string{"foo"}, 3470 }) 3471 if err != nil { 3472 return nil, err 3473 } 3474 if err := tc.Handshake(); err != nil { 3475 return nil, err 3476 } 3477 close(cancel) 3478 <-doReturned 3479 return tc, nil 3480 }, 3481 } 3482 c := &Client{Transport: tr} 3483 3484 _, err = c.Do(req) 3485 if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn { 3486 t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err) 3487 } 3488 3489 doReturned <- true 3490 <-madeRoundTripper 3491 <-handledPendingDial 3492 } 3493 3494 func TestTransportReuseConnection_Gzip_Chunked(t *testing.T) { 3495 testTransportReuseConnection_Gzip(t, true) 3496 } 3497 3498 func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) { 3499 testTransportReuseConnection_Gzip(t, false) 3500 } 3501 3502 // Make sure we re-use underlying TCP connection for gzipped responses too. 3503 func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) { 3504 setParallel(t) 3505 defer afterTest(t) 3506 addr := make(chan string, 2) 3507 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3508 addr <- r.RemoteAddr 3509 w.Header().Set("Content-Encoding", "gzip") 3510 if chunked { 3511 w.(Flusher).Flush() 3512 } 3513 w.Write(rgz) // arbitrary gzip response 3514 })) 3515 defer ts.Close() 3516 c := ts.Client() 3517 3518 for i := 0; i < 2; i++ { 3519 res, err := c.Get(ts.URL) 3520 if err != nil { 3521 t.Fatal(err) 3522 } 3523 buf := make([]byte, len(rgz)) 3524 if n, err := io.ReadFull(res.Body, buf); err != nil { 3525 t.Errorf("%d. ReadFull = %v, %v", i, n, err) 3526 } 3527 // Note: no res.Body.Close call. It should work without it, 3528 // since the flate.Reader's internal buffering will hit EOF 3529 // and that should be sufficient. 3530 } 3531 a1, a2 := <-addr, <-addr 3532 if a1 != a2 { 3533 t.Fatalf("didn't reuse connection") 3534 } 3535 } 3536 3537 func TestTransportResponseHeaderLength(t *testing.T) { 3538 setParallel(t) 3539 defer afterTest(t) 3540 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3541 if r.URL.Path == "/long" { 3542 w.Header().Set("Long", strings.Repeat("a", 1<<20)) 3543 } 3544 })) 3545 defer ts.Close() 3546 c := ts.Client() 3547 c.Transport.(*Transport).MaxResponseHeaderBytes = 512 << 10 3548 3549 if res, err := c.Get(ts.URL); err != nil { 3550 t.Fatal(err) 3551 } else { 3552 res.Body.Close() 3553 } 3554 3555 res, err := c.Get(ts.URL + "/long") 3556 if err == nil { 3557 defer res.Body.Close() 3558 var n int64 3559 for k, vv := range res.Header { 3560 for _, v := range vv { 3561 n += int64(len(k)) + int64(len(v)) 3562 } 3563 } 3564 t.Fatalf("Unexpected success. Got %v and %d bytes of response headers", res.Status, n) 3565 } 3566 if want := "server response headers exceeded 524288 bytes"; !strings.Contains(err.Error(), want) { 3567 t.Errorf("got error: %v; want %q", err, want) 3568 } 3569 } 3570 3571 func TestTransportEventTrace(t *testing.T) { testTransportEventTrace(t, h1Mode, false) } 3572 func TestTransportEventTrace_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, false) } 3573 3574 // test a non-nil httptrace.ClientTrace but with all hooks set to zero. 3575 func TestTransportEventTrace_NoHooks(t *testing.T) { testTransportEventTrace(t, h1Mode, true) } 3576 func TestTransportEventTrace_NoHooks_h2(t *testing.T) { testTransportEventTrace(t, h2Mode, true) } 3577 3578 func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { 3579 defer afterTest(t) 3580 const resBody = "some body" 3581 gotWroteReqEvent := make(chan struct{}) 3582 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3583 if _, err := ioutil.ReadAll(r.Body); err != nil { 3584 t.Error(err) 3585 } 3586 if !noHooks { 3587 select { 3588 case <-gotWroteReqEvent: 3589 case <-time.After(5 * time.Second): 3590 t.Error("timeout waiting for WroteRequest event") 3591 } 3592 } 3593 io.WriteString(w, resBody) 3594 })) 3595 defer cst.close() 3596 3597 cst.tr.ExpectContinueTimeout = 1 * time.Second 3598 3599 var mu sync.Mutex // guards buf 3600 var buf bytes.Buffer 3601 logf := func(format string, args ...interface{}) { 3602 mu.Lock() 3603 defer mu.Unlock() 3604 fmt.Fprintf(&buf, format, args...) 3605 buf.WriteByte('\n') 3606 } 3607 3608 addrStr := cst.ts.Listener.Addr().String() 3609 ip, port, err := net.SplitHostPort(addrStr) 3610 if err != nil { 3611 t.Fatal(err) 3612 } 3613 3614 // Install a fake DNS server. 3615 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3616 if host != "dns-is-faked.golang" { 3617 t.Errorf("unexpected DNS host lookup for %q", host) 3618 return nil, nil 3619 } 3620 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3621 }) 3622 3623 req, _ := NewRequest("POST", cst.scheme()+"://dns-is-faked.golang:"+port, strings.NewReader("some body")) 3624 trace := &httptrace.ClientTrace{ 3625 GetConn: func(hostPort string) { logf("Getting conn for %v ...", hostPort) }, 3626 GotConn: func(ci httptrace.GotConnInfo) { logf("got conn: %+v", ci) }, 3627 GotFirstResponseByte: func() { logf("first response byte") }, 3628 PutIdleConn: func(err error) { logf("PutIdleConn = %v", err) }, 3629 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNS start: %+v", e) }, 3630 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNS done: %+v", e) }, 3631 ConnectStart: func(network, addr string) { logf("ConnectStart: Connecting to %s %s ...", network, addr) }, 3632 ConnectDone: func(network, addr string, err error) { 3633 if err != nil { 3634 t.Errorf("ConnectDone: %v", err) 3635 } 3636 logf("ConnectDone: connected to %s %s = %v", network, addr, err) 3637 }, 3638 Wait100Continue: func() { logf("Wait100Continue") }, 3639 Got100Continue: func() { logf("Got100Continue") }, 3640 WroteRequest: func(e httptrace.WroteRequestInfo) { 3641 logf("WroteRequest: %+v", e) 3642 close(gotWroteReqEvent) 3643 }, 3644 } 3645 if h2 { 3646 trace.TLSHandshakeStart = func() { logf("tls handshake start") } 3647 trace.TLSHandshakeDone = func(s tls.ConnectionState, err error) { 3648 logf("tls handshake done. ConnectionState = %v \n err = %v", s, err) 3649 } 3650 } 3651 if noHooks { 3652 // zero out all func pointers, trying to get some path to crash 3653 *trace = httptrace.ClientTrace{} 3654 } 3655 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 3656 3657 req.Header.Set("Expect", "100-continue") 3658 res, err := cst.c.Do(req) 3659 if err != nil { 3660 t.Fatal(err) 3661 } 3662 logf("got roundtrip.response") 3663 slurp, err := ioutil.ReadAll(res.Body) 3664 if err != nil { 3665 t.Fatal(err) 3666 } 3667 logf("consumed body") 3668 if string(slurp) != resBody || res.StatusCode != 200 { 3669 t.Fatalf("Got %q, %v; want %q, 200 OK", slurp, res.Status, resBody) 3670 } 3671 res.Body.Close() 3672 3673 if noHooks { 3674 // Done at this point. Just testing a full HTTP 3675 // requests can happen with a trace pointing to a zero 3676 // ClientTrace, full of nil func pointers. 3677 return 3678 } 3679 3680 mu.Lock() 3681 got := buf.String() 3682 mu.Unlock() 3683 3684 wantOnce := func(sub string) { 3685 if strings.Count(got, sub) != 1 { 3686 t.Errorf("expected substring %q exactly once in output.", sub) 3687 } 3688 } 3689 wantOnceOrMore := func(sub string) { 3690 if strings.Count(got, sub) == 0 { 3691 t.Errorf("expected substring %q at least once in output.", sub) 3692 } 3693 } 3694 wantOnce("Getting conn for dns-is-faked.golang:" + port) 3695 wantOnce("DNS start: {Host:dns-is-faked.golang}") 3696 wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err:<nil> Coalesced:false}") 3697 wantOnce("got conn: {") 3698 wantOnceOrMore("Connecting to tcp " + addrStr) 3699 wantOnceOrMore("connected to tcp " + addrStr + " = <nil>") 3700 wantOnce("Reused:false WasIdle:false IdleTime:0s") 3701 wantOnce("first response byte") 3702 if h2 { 3703 wantOnce("tls handshake start") 3704 wantOnce("tls handshake done") 3705 } else { 3706 wantOnce("PutIdleConn = <nil>") 3707 } 3708 wantOnce("Wait100Continue") 3709 wantOnce("Got100Continue") 3710 wantOnce("WroteRequest: {Err:<nil>}") 3711 if strings.Contains(got, " to udp ") { 3712 t.Errorf("should not see UDP (DNS) connections") 3713 } 3714 if t.Failed() { 3715 t.Errorf("Output:\n%s", got) 3716 } 3717 } 3718 3719 var ( 3720 isDNSHijackedOnce sync.Once 3721 isDNSHijacked bool 3722 ) 3723 3724 func skipIfDNSHijacked(t *testing.T) { 3725 // Skip this test if the user is using a shady/ISP 3726 // DNS server hijacking queries. 3727 // See issues 16732, 16716. 3728 isDNSHijackedOnce.Do(func() { 3729 addrs, _ := net.LookupHost("dns-should-not-resolve.golang") 3730 isDNSHijacked = len(addrs) != 0 3731 }) 3732 if isDNSHijacked { 3733 t.Skip("skipping; test requires non-hijacking DNS server") 3734 } 3735 } 3736 3737 func TestTransportEventTraceRealDNS(t *testing.T) { 3738 skipIfDNSHijacked(t) 3739 defer afterTest(t) 3740 tr := &Transport{} 3741 defer tr.CloseIdleConnections() 3742 c := &Client{Transport: tr} 3743 3744 var mu sync.Mutex // guards buf 3745 var buf bytes.Buffer 3746 logf := func(format string, args ...interface{}) { 3747 mu.Lock() 3748 defer mu.Unlock() 3749 fmt.Fprintf(&buf, format, args...) 3750 buf.WriteByte('\n') 3751 } 3752 3753 req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil) 3754 trace := &httptrace.ClientTrace{ 3755 DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) }, 3756 DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) }, 3757 ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) }, 3758 ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) }, 3759 } 3760 req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 3761 3762 resp, err := c.Do(req) 3763 if err == nil { 3764 resp.Body.Close() 3765 t.Fatal("expected error during DNS lookup") 3766 } 3767 3768 mu.Lock() 3769 got := buf.String() 3770 mu.Unlock() 3771 3772 wantSub := func(sub string) { 3773 if !strings.Contains(got, sub) { 3774 t.Errorf("expected substring %q in output.", sub) 3775 } 3776 } 3777 wantSub("DNSStart: {Host:dns-should-not-resolve.golang}") 3778 wantSub("DNSDone: {Addrs:[] Err:") 3779 if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") { 3780 t.Errorf("should not see Connect events") 3781 } 3782 if t.Failed() { 3783 t.Errorf("Output:\n%s", got) 3784 } 3785 } 3786 3787 // Issue 14353: port can only contain digits. 3788 func TestTransportRejectsAlphaPort(t *testing.T) { 3789 res, err := Get("http://dummy.tld:123foo/bar") 3790 if err == nil { 3791 res.Body.Close() 3792 t.Fatal("unexpected success") 3793 } 3794 ue, ok := err.(*url.Error) 3795 if !ok { 3796 t.Fatalf("got %#v; want *url.Error", err) 3797 } 3798 got := ue.Err.Error() 3799 want := `invalid URL port "123foo"` 3800 if got != want { 3801 t.Errorf("got error %q; want %q", got, want) 3802 } 3803 } 3804 3805 // Test the httptrace.TLSHandshake{Start,Done} hooks with a https http1 3806 // connections. The http2 test is done in TestTransportEventTrace_h2 3807 func TestTLSHandshakeTrace(t *testing.T) { 3808 defer afterTest(t) 3809 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 3810 defer ts.Close() 3811 3812 var mu sync.Mutex 3813 var start, done bool 3814 trace := &httptrace.ClientTrace{ 3815 TLSHandshakeStart: func() { 3816 mu.Lock() 3817 defer mu.Unlock() 3818 start = true 3819 }, 3820 TLSHandshakeDone: func(s tls.ConnectionState, err error) { 3821 mu.Lock() 3822 defer mu.Unlock() 3823 done = true 3824 if err != nil { 3825 t.Fatal("Expected error to be nil but was:", err) 3826 } 3827 }, 3828 } 3829 3830 c := ts.Client() 3831 req, err := NewRequest("GET", ts.URL, nil) 3832 if err != nil { 3833 t.Fatal("Unable to construct test request:", err) 3834 } 3835 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) 3836 3837 r, err := c.Do(req) 3838 if err != nil { 3839 t.Fatal("Unexpected error making request:", err) 3840 } 3841 r.Body.Close() 3842 mu.Lock() 3843 defer mu.Unlock() 3844 if !start { 3845 t.Fatal("Expected TLSHandshakeStart to be called, but wasn't") 3846 } 3847 if !done { 3848 t.Fatal("Expected TLSHandshakeDone to be called, but wasnt't") 3849 } 3850 } 3851 3852 func TestTransportMaxIdleConns(t *testing.T) { 3853 defer afterTest(t) 3854 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3855 // No body for convenience. 3856 })) 3857 defer ts.Close() 3858 c := ts.Client() 3859 tr := c.Transport.(*Transport) 3860 tr.MaxIdleConns = 4 3861 3862 ip, port, err := net.SplitHostPort(ts.Listener.Addr().String()) 3863 if err != nil { 3864 t.Fatal(err) 3865 } 3866 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 3867 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 3868 }) 3869 3870 hitHost := func(n int) { 3871 req, _ := NewRequest("GET", fmt.Sprintf("http://host-%d.dns-is-faked.golang:"+port, n), nil) 3872 req = req.WithContext(ctx) 3873 res, err := c.Do(req) 3874 if err != nil { 3875 t.Fatal(err) 3876 } 3877 res.Body.Close() 3878 } 3879 for i := 0; i < 4; i++ { 3880 hitHost(i) 3881 } 3882 want := []string{ 3883 "|http|host-0.dns-is-faked.golang:" + port, 3884 "|http|host-1.dns-is-faked.golang:" + port, 3885 "|http|host-2.dns-is-faked.golang:" + port, 3886 "|http|host-3.dns-is-faked.golang:" + port, 3887 } 3888 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3889 t.Fatalf("idle conn keys mismatch.\n got: %q\nwant: %q\n", got, want) 3890 } 3891 3892 // Now hitting the 5th host should kick out the first host: 3893 hitHost(4) 3894 want = []string{ 3895 "|http|host-1.dns-is-faked.golang:" + port, 3896 "|http|host-2.dns-is-faked.golang:" + port, 3897 "|http|host-3.dns-is-faked.golang:" + port, 3898 "|http|host-4.dns-is-faked.golang:" + port, 3899 } 3900 if got := tr.IdleConnKeysForTesting(); !reflect.DeepEqual(got, want) { 3901 t.Fatalf("idle conn keys mismatch after 5th host.\n got: %q\nwant: %q\n", got, want) 3902 } 3903 } 3904 3905 func TestTransportIdleConnTimeout_h1(t *testing.T) { testTransportIdleConnTimeout(t, h1Mode) } 3906 func TestTransportIdleConnTimeout_h2(t *testing.T) { testTransportIdleConnTimeout(t, h2Mode) } 3907 func testTransportIdleConnTimeout(t *testing.T, h2 bool) { 3908 if testing.Short() { 3909 t.Skip("skipping in short mode") 3910 } 3911 defer afterTest(t) 3912 3913 const timeout = 1 * time.Second 3914 3915 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 3916 // No body for convenience. 3917 })) 3918 defer cst.close() 3919 tr := cst.tr 3920 tr.IdleConnTimeout = timeout 3921 defer tr.CloseIdleConnections() 3922 c := &Client{Transport: tr} 3923 3924 idleConns := func() []string { 3925 if h2 { 3926 return tr.IdleConnStrsForTesting_h2() 3927 } else { 3928 return tr.IdleConnStrsForTesting() 3929 } 3930 } 3931 3932 var conn string 3933 doReq := func(n int) { 3934 req, _ := NewRequest("GET", cst.ts.URL, nil) 3935 req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ 3936 PutIdleConn: func(err error) { 3937 if err != nil { 3938 t.Errorf("failed to keep idle conn: %v", err) 3939 } 3940 }, 3941 })) 3942 res, err := c.Do(req) 3943 if err != nil { 3944 t.Fatal(err) 3945 } 3946 res.Body.Close() 3947 conns := idleConns() 3948 if len(conns) != 1 { 3949 t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns) 3950 } 3951 if conn == "" { 3952 conn = conns[0] 3953 } 3954 if conn != conns[0] { 3955 t.Fatalf("req %v: cached connection changed; expected the same one throughout the test", n) 3956 } 3957 } 3958 for i := 0; i < 3; i++ { 3959 doReq(i) 3960 time.Sleep(timeout / 2) 3961 } 3962 time.Sleep(timeout * 3 / 2) 3963 if got := idleConns(); len(got) != 0 { 3964 t.Errorf("idle conns = %q; want none", got) 3965 } 3966 } 3967 3968 // Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an 3969 // HTTP/2 connection was established but but its caller no longer 3970 // wanted it. (Assuming the connection cache was enabled, which it is 3971 // by default) 3972 // 3973 // This test reproduced the crash by setting the IdleConnTimeout low 3974 // (to make the test reasonable) and then making a request which is 3975 // canceled by the DialTLS hook, which then also waits to return the 3976 // real connection until after the RoundTrip saw the error. Then we 3977 // know the successful tls.Dial from DialTLS will need to go into the 3978 // idle pool. Then we give it a of time to explode. 3979 func TestIdleConnH2Crash(t *testing.T) { 3980 setParallel(t) 3981 cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 3982 // nothing 3983 })) 3984 defer cst.close() 3985 3986 ctx, cancel := context.WithCancel(context.Background()) 3987 defer cancel() 3988 3989 sawDoErr := make(chan bool, 1) 3990 testDone := make(chan struct{}) 3991 defer close(testDone) 3992 3993 cst.tr.IdleConnTimeout = 5 * time.Millisecond 3994 cst.tr.DialTLS = func(network, addr string) (net.Conn, error) { 3995 c, err := tls.Dial(network, addr, &tls.Config{ 3996 InsecureSkipVerify: true, 3997 NextProtos: []string{"h2"}, 3998 }) 3999 if err != nil { 4000 t.Error(err) 4001 return nil, err 4002 } 4003 if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" { 4004 t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2") 4005 c.Close() 4006 return nil, errors.New("bogus") 4007 } 4008 4009 cancel() 4010 4011 failTimer := time.NewTimer(5 * time.Second) 4012 defer failTimer.Stop() 4013 select { 4014 case <-sawDoErr: 4015 case <-testDone: 4016 case <-failTimer.C: 4017 t.Error("timeout in DialTLS, waiting too long for cst.c.Do to fail") 4018 } 4019 return c, nil 4020 } 4021 4022 req, _ := NewRequest("GET", cst.ts.URL, nil) 4023 req = req.WithContext(ctx) 4024 res, err := cst.c.Do(req) 4025 if err == nil { 4026 res.Body.Close() 4027 t.Fatal("unexpected success") 4028 } 4029 sawDoErr <- true 4030 4031 // Wait for the explosion. 4032 time.Sleep(cst.tr.IdleConnTimeout * 10) 4033 } 4034 4035 type funcConn struct { 4036 net.Conn 4037 read func([]byte) (int, error) 4038 write func([]byte) (int, error) 4039 } 4040 4041 func (c funcConn) Read(p []byte) (int, error) { return c.read(p) } 4042 func (c funcConn) Write(p []byte) (int, error) { return c.write(p) } 4043 func (c funcConn) Close() error { return nil } 4044 4045 // Issue 16465: Transport.RoundTrip should return the raw net.Conn.Read error from Peek 4046 // back to the caller. 4047 func TestTransportReturnsPeekError(t *testing.T) { 4048 errValue := errors.New("specific error value") 4049 4050 wrote := make(chan struct{}) 4051 var wroteOnce sync.Once 4052 4053 tr := &Transport{ 4054 Dial: func(network, addr string) (net.Conn, error) { 4055 c := funcConn{ 4056 read: func([]byte) (int, error) { 4057 <-wrote 4058 return 0, errValue 4059 }, 4060 write: func(p []byte) (int, error) { 4061 wroteOnce.Do(func() { close(wrote) }) 4062 return len(p), nil 4063 }, 4064 } 4065 return c, nil 4066 }, 4067 } 4068 _, err := tr.RoundTrip(httptest.NewRequest("GET", "http://fake.tld/", nil)) 4069 if err != errValue { 4070 t.Errorf("error = %#v; want %v", err, errValue) 4071 } 4072 } 4073 4074 // Issue 13835: international domain names should work 4075 func TestTransportIDNA_h1(t *testing.T) { testTransportIDNA(t, h1Mode) } 4076 func TestTransportIDNA_h2(t *testing.T) { testTransportIDNA(t, h2Mode) } 4077 func testTransportIDNA(t *testing.T, h2 bool) { 4078 defer afterTest(t) 4079 4080 const uniDomain = "." 4081 const punyDomain = "xn--c1ae0ajs.xn--c1aw" 4082 4083 var port string 4084 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 4085 want := punyDomain + ":" + port 4086 if r.Host != want { 4087 t.Errorf("Host header = %q; want %q", r.Host, want) 4088 } 4089 if h2 { 4090 if r.TLS == nil { 4091 t.Errorf("r.TLS == nil") 4092 } else if r.TLS.ServerName != punyDomain { 4093 t.Errorf("TLS.ServerName = %q; want %q", r.TLS.ServerName, punyDomain) 4094 } 4095 } 4096 w.Header().Set("Hit-Handler", "1") 4097 })) 4098 defer cst.close() 4099 4100 ip, port, err := net.SplitHostPort(cst.ts.Listener.Addr().String()) 4101 if err != nil { 4102 t.Fatal(err) 4103 } 4104 4105 // Install a fake DNS server. 4106 ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) { 4107 if host != punyDomain { 4108 t.Errorf("got DNS host lookup for %q; want %q", host, punyDomain) 4109 return nil, nil 4110 } 4111 return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil 4112 }) 4113 4114 req, _ := NewRequest("GET", cst.scheme()+"://"+uniDomain+":"+port, nil) 4115 trace := &httptrace.ClientTrace{ 4116 GetConn: func(hostPort string) { 4117 want := net.JoinHostPort(punyDomain, port) 4118 if hostPort != want { 4119 t.Errorf("getting conn for %q; want %q", hostPort, want) 4120 } 4121 }, 4122 DNSStart: func(e httptrace.DNSStartInfo) { 4123 if e.Host != punyDomain { 4124 t.Errorf("DNSStart Host = %q; want %q", e.Host, punyDomain) 4125 } 4126 }, 4127 } 4128 req = req.WithContext(httptrace.WithClientTrace(ctx, trace)) 4129 4130 res, err := cst.tr.RoundTrip(req) 4131 if err != nil { 4132 t.Fatal(err) 4133 } 4134 defer res.Body.Close() 4135 if res.Header.Get("Hit-Handler") != "1" { 4136 out, err := httputil.DumpResponse(res, true) 4137 if err != nil { 4138 t.Fatal(err) 4139 } 4140 t.Errorf("Response body wasn't from Handler. Got:\n%s\n", out) 4141 } 4142 } 4143 4144 // Issue 13290: send User-Agent in proxy CONNECT 4145 func TestTransportProxyConnectHeader(t *testing.T) { 4146 defer afterTest(t) 4147 reqc := make(chan *Request, 1) 4148 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 4149 if r.Method != "CONNECT" { 4150 t.Errorf("method = %q; want CONNECT", r.Method) 4151 } 4152 reqc <- r 4153 c, _, err := w.(Hijacker).Hijack() 4154 if err != nil { 4155 t.Errorf("Hijack: %v", err) 4156 return 4157 } 4158 c.Close() 4159 })) 4160 defer ts.Close() 4161 4162 c := ts.Client() 4163 c.Transport.(*Transport).Proxy = func(r *Request) (*url.URL, error) { 4164 return url.Parse(ts.URL) 4165 } 4166 c.Transport.(*Transport).ProxyConnectHeader = Header{ 4167 "User-Agent": {"foo"}, 4168 "Other": {"bar"}, 4169 } 4170 4171 res, err := c.Get("https://dummy.tld/") // https to force a CONNECT 4172 if err == nil { 4173 res.Body.Close() 4174 t.Errorf("unexpected success") 4175 } 4176 select { 4177 case <-time.After(3 * time.Second): 4178 t.Fatal("timeout") 4179 case r := <-reqc: 4180 if got, want := r.Header.Get("User-Agent"), "foo"; got != want { 4181 t.Errorf("CONNECT request User-Agent = %q; want %q", got, want) 4182 } 4183 if got, want := r.Header.Get("Other"), "bar"; got != want { 4184 t.Errorf("CONNECT request Other = %q; want %q", got, want) 4185 } 4186 } 4187 } 4188 4189 var errFakeRoundTrip = errors.New("fake roundtrip") 4190 4191 type funcRoundTripper func() 4192 4193 func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) { 4194 fn() 4195 return nil, errFakeRoundTrip 4196 } 4197 4198 func wantBody(res *Response, err error, want string) error { 4199 if err != nil { 4200 return err 4201 } 4202 slurp, err := ioutil.ReadAll(res.Body) 4203 if err != nil { 4204 return fmt.Errorf("error reading body: %v", err) 4205 } 4206 if string(slurp) != want { 4207 return fmt.Errorf("body = %q; want %q", slurp, want) 4208 } 4209 if err := res.Body.Close(); err != nil { 4210 return fmt.Errorf("body Close = %v", err) 4211 } 4212 return nil 4213 } 4214 4215 func newLocalListener(t *testing.T) net.Listener { 4216 ln, err := net.Listen("tcp", "127.0.0.1:0") 4217 if err != nil { 4218 ln, err = net.Listen("tcp6", "[::1]:0") 4219 } 4220 if err != nil { 4221 t.Fatal(err) 4222 } 4223 return ln 4224 } 4225 4226 type countCloseReader struct { 4227 n *int 4228 io.Reader 4229 } 4230 4231 func (cr countCloseReader) Close() error { 4232 (*cr.n)++ 4233 return nil 4234 } 4235 4236 // rgz is a gzip quine that uncompresses to itself. 4237 var rgz = []byte{ 4238 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 4239 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 4240 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 4241 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 4242 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 4243 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 4244 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 4245 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 4246 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 4247 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 4248 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 4249 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 4250 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 4251 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 4252 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 4253 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 4254 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 4255 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 4256 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 4257 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 4258 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 4259 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 4260 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 4261 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 4262 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 4263 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 4264 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 4265 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 4266 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 4267 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 4268 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 4269 0x00, 0x00, 4270 } 4271 4272 // Ensure that a missing status doesn't make the server panic 4273 // See Issue https://golang.org/issues/21701 4274 func TestMissingStatusNoPanic(t *testing.T) { 4275 t.Parallel() 4276 4277 const want = "unknown status code" 4278 4279 ln := newLocalListener(t) 4280 addr := ln.Addr().String() 4281 shutdown := make(chan bool, 1) 4282 done := make(chan bool) 4283 fullAddrURL := fmt.Sprintf("http://%s", addr) 4284 raw := "HTTP/1.1 400\r\n" + 4285 "Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" + 4286 "Content-Type: text/html; charset=utf-8\r\n" + 4287 "Content-Length: 10\r\n" + 4288 "Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT\r\n" + 4289 "Vary: Accept-Encoding\r\n\r\n" + 4290 "Aloha Olaa" 4291 4292 go func() { 4293 defer func() { 4294 ln.Close() 4295 close(done) 4296 }() 4297 4298 conn, _ := ln.Accept() 4299 if conn != nil { 4300 io.WriteString(conn, raw) 4301 ioutil.ReadAll(conn) 4302 conn.Close() 4303 } 4304 }() 4305 4306 proxyURL, err := url.Parse(fullAddrURL) 4307 if err != nil { 4308 t.Fatalf("proxyURL: %v", err) 4309 } 4310 4311 tr := &Transport{Proxy: ProxyURL(proxyURL)} 4312 4313 req, _ := NewRequest("GET", "https://golang.org/", nil) 4314 res, err, panicked := doFetchCheckPanic(tr, req) 4315 if panicked { 4316 t.Error("panicked, expecting an error") 4317 } 4318 if res != nil && res.Body != nil { 4319 io.Copy(ioutil.Discard, res.Body) 4320 res.Body.Close() 4321 } 4322 4323 if err == nil || !strings.Contains(err.Error(), want) { 4324 t.Errorf("got=%v want=%q", err, want) 4325 } 4326 4327 close(shutdown) 4328 <-done 4329 } 4330 4331 func doFetchCheckPanic(tr *Transport, req *Request) (res *Response, err error, panicked bool) { 4332 defer func() { 4333 if r := recover(); r != nil { 4334 panicked = true 4335 } 4336 }() 4337 res, err = tr.RoundTrip(req) 4338 return 4339 } 4340 4341 // Issue 22330: do not allow the response body to be read when the status code 4342 // forbids a response body. 4343 func TestNoBodyOnChunked304Response(t *testing.T) { 4344 defer afterTest(t) 4345 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 4346 conn, buf, _ := w.(Hijacker).Hijack() 4347 buf.Write([]byte("HTTP/1.1 304 NOT MODIFIED\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n")) 4348 buf.Flush() 4349 conn.Close() 4350 })) 4351 defer cst.close() 4352 4353 // Our test server above is sending back bogus data after the 4354 // response (the "0\r\n\r\n" part), which causes the Transport 4355 // code to log spam. Disable keep-alives so we never even try 4356 // to reuse the connection. 4357 cst.tr.DisableKeepAlives = true 4358 4359 res, err := cst.c.Get(cst.ts.URL) 4360 if err != nil { 4361 t.Fatal(err) 4362 } 4363 4364 if res.Body != NoBody { 4365 t.Errorf("Unexpected body on 304 response") 4366 } 4367 } 4368