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