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