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