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