github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/src/net/http/transport_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Tests for transport.go 6 7 package http_test 8 9 import ( 10 "bufio" 11 "bytes" 12 "compress/gzip" 13 "crypto/rand" 14 "crypto/tls" 15 "errors" 16 "fmt" 17 "io" 18 "io/ioutil" 19 "log" 20 "net" 21 "net/http" 22 . "net/http" 23 "net/http/httptest" 24 "net/url" 25 "os" 26 "runtime" 27 "strconv" 28 "strings" 29 "sync" 30 "testing" 31 "time" 32 ) 33 34 // TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close 35 // and then verify that the final 2 responses get errors back. 36 37 // hostPortHandler writes back the client's "host:port". 38 var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 39 if r.FormValue("close") == "true" { 40 w.Header().Set("Connection", "close") 41 } 42 w.Write([]byte(r.RemoteAddr)) 43 }) 44 45 // testCloseConn is a net.Conn tracked by a testConnSet. 46 type testCloseConn struct { 47 net.Conn 48 set *testConnSet 49 } 50 51 func (c *testCloseConn) Close() error { 52 c.set.remove(c) 53 return c.Conn.Close() 54 } 55 56 // testConnSet tracks a set of TCP connections and whether they've 57 // been closed. 58 type testConnSet struct { 59 t *testing.T 60 mu sync.Mutex // guards closed and list 61 closed map[net.Conn]bool 62 list []net.Conn // in order created 63 } 64 65 func (tcs *testConnSet) insert(c net.Conn) { 66 tcs.mu.Lock() 67 defer tcs.mu.Unlock() 68 tcs.closed[c] = false 69 tcs.list = append(tcs.list, c) 70 } 71 72 func (tcs *testConnSet) remove(c net.Conn) { 73 tcs.mu.Lock() 74 defer tcs.mu.Unlock() 75 tcs.closed[c] = true 76 } 77 78 // some tests use this to manage raw tcp connections for later inspection 79 func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) { 80 connSet := &testConnSet{ 81 t: t, 82 closed: make(map[net.Conn]bool), 83 } 84 dial := func(n, addr string) (net.Conn, error) { 85 c, err := net.Dial(n, addr) 86 if err != nil { 87 return nil, err 88 } 89 tc := &testCloseConn{c, connSet} 90 connSet.insert(tc) 91 return tc, nil 92 } 93 return connSet, dial 94 } 95 96 func (tcs *testConnSet) check(t *testing.T) { 97 tcs.mu.Lock() 98 defer tcs.mu.Unlock() 99 for i := 4; i >= 0; i-- { 100 for i, c := range tcs.list { 101 if tcs.closed[c] { 102 continue 103 } 104 if i != 0 { 105 tcs.mu.Unlock() 106 time.Sleep(50 * time.Millisecond) 107 tcs.mu.Lock() 108 continue 109 } 110 t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list)) 111 } 112 } 113 } 114 115 // Two subsequent requests and verify their response is the same. 116 // The response from the server is our own IP:port 117 func TestTransportKeepAlives(t *testing.T) { 118 defer afterTest(t) 119 ts := httptest.NewServer(hostPortHandler) 120 defer ts.Close() 121 122 for _, disableKeepAlive := range []bool{false, true} { 123 tr := &Transport{DisableKeepAlives: disableKeepAlive} 124 defer tr.CloseIdleConnections() 125 c := &Client{Transport: tr} 126 127 fetch := func(n int) string { 128 res, err := c.Get(ts.URL) 129 if err != nil { 130 t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err) 131 } 132 body, err := ioutil.ReadAll(res.Body) 133 if err != nil { 134 t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err) 135 } 136 return string(body) 137 } 138 139 body1 := fetch(1) 140 body2 := fetch(2) 141 142 bodiesDiffer := body1 != body2 143 if bodiesDiffer != disableKeepAlive { 144 t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 145 disableKeepAlive, bodiesDiffer, body1, body2) 146 } 147 } 148 } 149 150 func TestTransportConnectionCloseOnResponse(t *testing.T) { 151 defer afterTest(t) 152 ts := httptest.NewServer(hostPortHandler) 153 defer ts.Close() 154 155 connSet, testDial := makeTestDial(t) 156 157 for _, connectionClose := range []bool{false, true} { 158 tr := &Transport{ 159 Dial: testDial, 160 } 161 c := &Client{Transport: tr} 162 163 fetch := func(n int) string { 164 req := new(Request) 165 var err error 166 req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose)) 167 if err != nil { 168 t.Fatalf("URL parse error: %v", err) 169 } 170 req.Method = "GET" 171 req.Proto = "HTTP/1.1" 172 req.ProtoMajor = 1 173 req.ProtoMinor = 1 174 175 res, err := c.Do(req) 176 if err != nil { 177 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) 178 } 179 defer res.Body.Close() 180 body, err := ioutil.ReadAll(res.Body) 181 if err != nil { 182 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) 183 } 184 return string(body) 185 } 186 187 body1 := fetch(1) 188 body2 := fetch(2) 189 bodiesDiffer := body1 != body2 190 if bodiesDiffer != connectionClose { 191 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 192 connectionClose, bodiesDiffer, body1, body2) 193 } 194 195 tr.CloseIdleConnections() 196 } 197 198 connSet.check(t) 199 } 200 201 func TestTransportConnectionCloseOnRequest(t *testing.T) { 202 defer afterTest(t) 203 ts := httptest.NewServer(hostPortHandler) 204 defer ts.Close() 205 206 connSet, testDial := makeTestDial(t) 207 208 for _, connectionClose := range []bool{false, true} { 209 tr := &Transport{ 210 Dial: testDial, 211 } 212 c := &Client{Transport: tr} 213 214 fetch := func(n int) string { 215 req := new(Request) 216 var err error 217 req.URL, err = url.Parse(ts.URL) 218 if err != nil { 219 t.Fatalf("URL parse error: %v", err) 220 } 221 req.Method = "GET" 222 req.Proto = "HTTP/1.1" 223 req.ProtoMajor = 1 224 req.ProtoMinor = 1 225 req.Close = connectionClose 226 227 res, err := c.Do(req) 228 if err != nil { 229 t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) 230 } 231 body, err := ioutil.ReadAll(res.Body) 232 if err != nil { 233 t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) 234 } 235 return string(body) 236 } 237 238 body1 := fetch(1) 239 body2 := fetch(2) 240 bodiesDiffer := body1 != body2 241 if bodiesDiffer != connectionClose { 242 t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", 243 connectionClose, bodiesDiffer, body1, body2) 244 } 245 246 tr.CloseIdleConnections() 247 } 248 249 connSet.check(t) 250 } 251 252 func TestTransportIdleCacheKeys(t *testing.T) { 253 defer afterTest(t) 254 ts := httptest.NewServer(hostPortHandler) 255 defer ts.Close() 256 257 tr := &Transport{DisableKeepAlives: false} 258 c := &Client{Transport: tr} 259 260 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 261 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) 262 } 263 264 resp, err := c.Get(ts.URL) 265 if err != nil { 266 t.Error(err) 267 } 268 ioutil.ReadAll(resp.Body) 269 270 keys := tr.IdleConnKeysForTesting() 271 if e, g := 1, len(keys); e != g { 272 t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g) 273 } 274 275 if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e { 276 t.Errorf("Expected idle cache key %q; got %q", e, keys[0]) 277 } 278 279 tr.CloseIdleConnections() 280 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 281 t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g) 282 } 283 } 284 285 // Tests that the HTTP transport re-uses connections when a client 286 // reads to the end of a response Body without closing it. 287 func TestTransportReadToEndReusesConn(t *testing.T) { 288 defer afterTest(t) 289 const msg = "foobar" 290 291 var addrSeen map[string]int 292 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 293 addrSeen[r.RemoteAddr]++ 294 if r.URL.Path == "/chunked/" { 295 w.WriteHeader(200) 296 w.(http.Flusher).Flush() 297 } else { 298 w.Header().Set("Content-Type", strconv.Itoa(len(msg))) 299 w.WriteHeader(200) 300 } 301 w.Write([]byte(msg)) 302 })) 303 defer ts.Close() 304 305 buf := make([]byte, len(msg)) 306 307 for pi, path := range []string{"/content-length/", "/chunked/"} { 308 wantLen := []int{len(msg), -1}[pi] 309 addrSeen = make(map[string]int) 310 for i := 0; i < 3; i++ { 311 res, err := http.Get(ts.URL + path) 312 if err != nil { 313 t.Errorf("Get %s: %v", path, err) 314 continue 315 } 316 // We want to close this body eventually (before the 317 // defer afterTest at top runs), but not before the 318 // len(addrSeen) check at the bottom of this test, 319 // since Closing this early in the loop would risk 320 // making connections be re-used for the wrong reason. 321 defer res.Body.Close() 322 323 if res.ContentLength != int64(wantLen) { 324 t.Errorf("%s res.ContentLength = %d; want %d", path, res.ContentLength, wantLen) 325 } 326 n, err := res.Body.Read(buf) 327 if n != len(msg) || err != io.EOF { 328 t.Errorf("%s Read = %v, %v; want %d, EOF", path, n, err, len(msg)) 329 } 330 } 331 if len(addrSeen) != 1 { 332 t.Errorf("for %s, server saw %d distinct client addresses; want 1", path, len(addrSeen)) 333 } 334 } 335 } 336 337 func TestTransportMaxPerHostIdleConns(t *testing.T) { 338 defer afterTest(t) 339 resch := make(chan string) 340 gotReq := make(chan bool) 341 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 342 gotReq <- true 343 msg := <-resch 344 _, err := w.Write([]byte(msg)) 345 if err != nil { 346 t.Fatalf("Write: %v", err) 347 } 348 })) 349 defer ts.Close() 350 maxIdleConns := 2 351 tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns} 352 c := &Client{Transport: tr} 353 354 // Start 3 outstanding requests and wait for the server to get them. 355 // Their responses will hang until we write to resch, though. 356 donech := make(chan bool) 357 doReq := func() { 358 resp, err := c.Get(ts.URL) 359 if err != nil { 360 t.Error(err) 361 return 362 } 363 if _, err := ioutil.ReadAll(resp.Body); err != nil { 364 t.Errorf("ReadAll: %v", err) 365 return 366 } 367 donech <- true 368 } 369 go doReq() 370 <-gotReq 371 go doReq() 372 <-gotReq 373 go doReq() 374 <-gotReq 375 376 if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g { 377 t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g) 378 } 379 380 resch <- "res1" 381 <-donech 382 keys := tr.IdleConnKeysForTesting() 383 if e, g := 1, len(keys); e != g { 384 t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g) 385 } 386 cacheKey := "|http|" + ts.Listener.Addr().String() 387 if keys[0] != cacheKey { 388 t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0]) 389 } 390 if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g { 391 t.Errorf("after first response, expected %d idle conns; got %d", e, g) 392 } 393 394 resch <- "res2" 395 <-donech 396 if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g { 397 t.Errorf("after second response, expected %d idle conns; got %d", e, g) 398 } 399 400 resch <- "res3" 401 <-donech 402 if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g { 403 t.Errorf("after third response, still expected %d idle conns; got %d", e, g) 404 } 405 } 406 407 func TestTransportServerClosingUnexpectedly(t *testing.T) { 408 defer afterTest(t) 409 ts := httptest.NewServer(hostPortHandler) 410 defer ts.Close() 411 412 tr := &Transport{} 413 c := &Client{Transport: tr} 414 415 fetch := func(n, retries int) string { 416 condFatalf := func(format string, arg ...interface{}) { 417 if retries <= 0 { 418 t.Fatalf(format, arg...) 419 } 420 t.Logf("retrying shortly after expected error: "+format, arg...) 421 time.Sleep(time.Second / time.Duration(retries)) 422 } 423 for retries >= 0 { 424 retries-- 425 res, err := c.Get(ts.URL) 426 if err != nil { 427 condFatalf("error in req #%d, GET: %v", n, err) 428 continue 429 } 430 body, err := ioutil.ReadAll(res.Body) 431 if err != nil { 432 condFatalf("error in req #%d, ReadAll: %v", n, err) 433 continue 434 } 435 res.Body.Close() 436 return string(body) 437 } 438 panic("unreachable") 439 } 440 441 body1 := fetch(1, 0) 442 body2 := fetch(2, 0) 443 444 ts.CloseClientConnections() // surprise! 445 446 // This test has an expected race. Sleeping for 25 ms prevents 447 // it on most fast machines, causing the next fetch() call to 448 // succeed quickly. But if we do get errors, fetch() will retry 5 449 // times with some delays between. 450 time.Sleep(25 * time.Millisecond) 451 452 body3 := fetch(3, 5) 453 454 if body1 != body2 { 455 t.Errorf("expected body1 and body2 to be equal") 456 } 457 if body2 == body3 { 458 t.Errorf("expected body2 and body3 to be different") 459 } 460 } 461 462 // Test for http://golang.org/issue/2616 (appropriate issue number) 463 // This fails pretty reliably with GOMAXPROCS=100 or something high. 464 func TestStressSurpriseServerCloses(t *testing.T) { 465 defer afterTest(t) 466 if testing.Short() { 467 t.Skip("skipping test in short mode") 468 } 469 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 470 w.Header().Set("Content-Length", "5") 471 w.Header().Set("Content-Type", "text/plain") 472 w.Write([]byte("Hello")) 473 w.(Flusher).Flush() 474 conn, buf, _ := w.(Hijacker).Hijack() 475 buf.Flush() 476 conn.Close() 477 })) 478 defer ts.Close() 479 480 tr := &Transport{DisableKeepAlives: false} 481 c := &Client{Transport: tr} 482 483 // Do a bunch of traffic from different goroutines. Send to activityc 484 // after each request completes, regardless of whether it failed. 485 const ( 486 numClients = 50 487 reqsPerClient = 250 488 ) 489 activityc := make(chan bool) 490 for i := 0; i < numClients; i++ { 491 go func() { 492 for i := 0; i < reqsPerClient; i++ { 493 res, err := c.Get(ts.URL) 494 if err == nil { 495 // We expect errors since the server is 496 // hanging up on us after telling us to 497 // send more requests, so we don't 498 // actually care what the error is. 499 // But we want to close the body in cases 500 // where we won the race. 501 res.Body.Close() 502 } 503 activityc <- true 504 } 505 }() 506 } 507 508 // Make sure all the request come back, one way or another. 509 for i := 0; i < numClients*reqsPerClient; i++ { 510 select { 511 case <-activityc: 512 case <-time.After(5 * time.Second): 513 t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile") 514 } 515 } 516 } 517 518 // TestTransportHeadResponses verifies that we deal with Content-Lengths 519 // with no bodies properly 520 func TestTransportHeadResponses(t *testing.T) { 521 defer afterTest(t) 522 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 523 if r.Method != "HEAD" { 524 panic("expected HEAD; got " + r.Method) 525 } 526 w.Header().Set("Content-Length", "123") 527 w.WriteHeader(200) 528 })) 529 defer ts.Close() 530 531 tr := &Transport{DisableKeepAlives: false} 532 c := &Client{Transport: tr} 533 for i := 0; i < 2; i++ { 534 res, err := c.Head(ts.URL) 535 if err != nil { 536 t.Errorf("error on loop %d: %v", i, err) 537 continue 538 } 539 if e, g := "123", res.Header.Get("Content-Length"); e != g { 540 t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g) 541 } 542 if e, g := int64(123), res.ContentLength; e != g { 543 t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g) 544 } 545 if all, err := ioutil.ReadAll(res.Body); err != nil { 546 t.Errorf("loop %d: Body ReadAll: %v", i, err) 547 } else if len(all) != 0 { 548 t.Errorf("Bogus body %q", all) 549 } 550 } 551 } 552 553 // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding 554 // on responses to HEAD requests. 555 func TestTransportHeadChunkedResponse(t *testing.T) { 556 defer afterTest(t) 557 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 558 if r.Method != "HEAD" { 559 panic("expected HEAD; got " + r.Method) 560 } 561 w.Header().Set("Transfer-Encoding", "chunked") // client should ignore 562 w.Header().Set("x-client-ipport", r.RemoteAddr) 563 w.WriteHeader(200) 564 })) 565 defer ts.Close() 566 567 tr := &Transport{DisableKeepAlives: false} 568 c := &Client{Transport: tr} 569 570 res1, err := c.Head(ts.URL) 571 if err != nil { 572 t.Fatalf("request 1 error: %v", err) 573 } 574 res2, err := c.Head(ts.URL) 575 if err != nil { 576 t.Fatalf("request 2 error: %v", err) 577 } 578 if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 { 579 t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2) 580 } 581 } 582 583 var roundTripTests = []struct { 584 accept string 585 expectAccept string 586 compressed bool 587 }{ 588 // Requests with no accept-encoding header use transparent compression 589 {"", "gzip", false}, 590 // Requests with other accept-encoding should pass through unmodified 591 {"foo", "foo", false}, 592 // Requests with accept-encoding == gzip should be passed through 593 {"gzip", "gzip", true}, 594 } 595 596 // Test that the modification made to the Request by the RoundTripper is cleaned up 597 func TestRoundTripGzip(t *testing.T) { 598 defer afterTest(t) 599 const responseBody = "test response body" 600 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 601 accept := req.Header.Get("Accept-Encoding") 602 if expect := req.FormValue("expect_accept"); accept != expect { 603 t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q", 604 req.FormValue("testnum"), accept, expect) 605 } 606 if accept == "gzip" { 607 rw.Header().Set("Content-Encoding", "gzip") 608 gz := gzip.NewWriter(rw) 609 gz.Write([]byte(responseBody)) 610 gz.Close() 611 } else { 612 rw.Header().Set("Content-Encoding", accept) 613 rw.Write([]byte(responseBody)) 614 } 615 })) 616 defer ts.Close() 617 618 for i, test := range roundTripTests { 619 // Test basic request (no accept-encoding) 620 req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil) 621 if test.accept != "" { 622 req.Header.Set("Accept-Encoding", test.accept) 623 } 624 res, err := DefaultTransport.RoundTrip(req) 625 var body []byte 626 if test.compressed { 627 var r *gzip.Reader 628 r, err = gzip.NewReader(res.Body) 629 if err != nil { 630 t.Errorf("%d. gzip NewReader: %v", i, err) 631 continue 632 } 633 body, err = ioutil.ReadAll(r) 634 res.Body.Close() 635 } else { 636 body, err = ioutil.ReadAll(res.Body) 637 } 638 if err != nil { 639 t.Errorf("%d. Error: %q", i, err) 640 continue 641 } 642 if g, e := string(body), responseBody; g != e { 643 t.Errorf("%d. body = %q; want %q", i, g, e) 644 } 645 if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e { 646 t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e) 647 } 648 if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e { 649 t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e) 650 } 651 } 652 653 } 654 655 func TestTransportGzip(t *testing.T) { 656 defer afterTest(t) 657 const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 658 const nRandBytes = 1024 * 1024 659 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 660 if req.Method == "HEAD" { 661 if g := req.Header.Get("Accept-Encoding"); g != "" { 662 t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g) 663 } 664 return 665 } 666 if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e { 667 t.Errorf("Accept-Encoding = %q, want %q", g, e) 668 } 669 rw.Header().Set("Content-Encoding", "gzip") 670 671 var w io.Writer = rw 672 var buf bytes.Buffer 673 if req.FormValue("chunked") == "0" { 674 w = &buf 675 defer io.Copy(rw, &buf) 676 defer func() { 677 rw.Header().Set("Content-Length", strconv.Itoa(buf.Len())) 678 }() 679 } 680 gz := gzip.NewWriter(w) 681 gz.Write([]byte(testString)) 682 if req.FormValue("body") == "large" { 683 io.CopyN(gz, rand.Reader, nRandBytes) 684 } 685 gz.Close() 686 })) 687 defer ts.Close() 688 689 for _, chunked := range []string{"1", "0"} { 690 c := &Client{Transport: &Transport{}} 691 692 // First fetch something large, but only read some of it. 693 res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked) 694 if err != nil { 695 t.Fatalf("large get: %v", err) 696 } 697 buf := make([]byte, len(testString)) 698 n, err := io.ReadFull(res.Body, buf) 699 if err != nil { 700 t.Fatalf("partial read of large response: size=%d, %v", n, err) 701 } 702 if e, g := testString, string(buf); e != g { 703 t.Errorf("partial read got %q, expected %q", g, e) 704 } 705 res.Body.Close() 706 // Read on the body, even though it's closed 707 n, err = res.Body.Read(buf) 708 if n != 0 || err == nil { 709 t.Errorf("expected error post-closed large Read; got = %d, %v", n, err) 710 } 711 712 // Then something small. 713 res, err = c.Get(ts.URL + "/?chunked=" + chunked) 714 if err != nil { 715 t.Fatal(err) 716 } 717 body, err := ioutil.ReadAll(res.Body) 718 if err != nil { 719 t.Fatal(err) 720 } 721 if g, e := string(body), testString; g != e { 722 t.Fatalf("body = %q; want %q", g, e) 723 } 724 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 725 t.Fatalf("Content-Encoding = %q; want %q", g, e) 726 } 727 728 // Read on the body after it's been fully read: 729 n, err = res.Body.Read(buf) 730 if n != 0 || err == nil { 731 t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err) 732 } 733 res.Body.Close() 734 n, err = res.Body.Read(buf) 735 if n != 0 || err == nil { 736 t.Errorf("expected Read error after Close; got %d, %v", n, err) 737 } 738 } 739 740 // And a HEAD request too, because they're always weird. 741 c := &Client{Transport: &Transport{}} 742 res, err := c.Head(ts.URL) 743 if err != nil { 744 t.Fatalf("Head: %v", err) 745 } 746 if res.StatusCode != 200 { 747 t.Errorf("Head status=%d; want=200", res.StatusCode) 748 } 749 } 750 751 func TestTransportProxy(t *testing.T) { 752 defer afterTest(t) 753 ch := make(chan string, 1) 754 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 755 ch <- "real server" 756 })) 757 defer ts.Close() 758 proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 759 ch <- "proxy for " + r.URL.String() 760 })) 761 defer proxy.Close() 762 763 pu, err := url.Parse(proxy.URL) 764 if err != nil { 765 t.Fatal(err) 766 } 767 c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}} 768 c.Head(ts.URL) 769 got := <-ch 770 want := "proxy for " + ts.URL + "/" 771 if got != want { 772 t.Errorf("want %q, got %q", want, got) 773 } 774 } 775 776 // TestTransportGzipRecursive sends a gzip quine and checks that the 777 // client gets the same value back. This is more cute than anything, 778 // but checks that we don't recurse forever, and checks that 779 // Content-Encoding is removed. 780 func TestTransportGzipRecursive(t *testing.T) { 781 defer afterTest(t) 782 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 783 w.Header().Set("Content-Encoding", "gzip") 784 w.Write(rgz) 785 })) 786 defer ts.Close() 787 788 c := &Client{Transport: &Transport{}} 789 res, err := c.Get(ts.URL) 790 if err != nil { 791 t.Fatal(err) 792 } 793 body, err := ioutil.ReadAll(res.Body) 794 if err != nil { 795 t.Fatal(err) 796 } 797 if !bytes.Equal(body, rgz) { 798 t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x", 799 body, rgz) 800 } 801 if g, e := res.Header.Get("Content-Encoding"), ""; g != e { 802 t.Fatalf("Content-Encoding = %q; want %q", g, e) 803 } 804 } 805 806 // golang.org/issue/7750: request fails when server replies with 807 // a short gzip body 808 func TestTransportGzipShort(t *testing.T) { 809 defer afterTest(t) 810 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 811 w.Header().Set("Content-Encoding", "gzip") 812 w.Write([]byte{0x1f, 0x8b}) 813 })) 814 defer ts.Close() 815 816 tr := &Transport{} 817 defer tr.CloseIdleConnections() 818 c := &Client{Transport: tr} 819 res, err := c.Get(ts.URL) 820 if err != nil { 821 t.Fatal(err) 822 } 823 defer res.Body.Close() 824 _, err = ioutil.ReadAll(res.Body) 825 if err == nil { 826 t.Fatal("Expect an error from reading a body.") 827 } 828 if err != io.ErrUnexpectedEOF { 829 t.Errorf("ReadAll error = %v; want io.ErrUnexpectedEOF", err) 830 } 831 } 832 833 // tests that persistent goroutine connections shut down when no longer desired. 834 func TestTransportPersistConnLeak(t *testing.T) { 835 if runtime.GOOS == "plan9" { 836 t.Skip("skipping test; see http://golang.org/issue/7237") 837 } 838 defer afterTest(t) 839 gotReqCh := make(chan bool) 840 unblockCh := make(chan bool) 841 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 842 gotReqCh <- true 843 <-unblockCh 844 w.Header().Set("Content-Length", "0") 845 w.WriteHeader(204) 846 })) 847 defer ts.Close() 848 849 tr := &Transport{} 850 c := &Client{Transport: tr} 851 852 n0 := runtime.NumGoroutine() 853 854 const numReq = 25 855 didReqCh := make(chan bool) 856 for i := 0; i < numReq; i++ { 857 go func() { 858 res, err := c.Get(ts.URL) 859 didReqCh <- true 860 if err != nil { 861 t.Errorf("client fetch error: %v", err) 862 return 863 } 864 res.Body.Close() 865 }() 866 } 867 868 // Wait for all goroutines to be stuck in the Handler. 869 for i := 0; i < numReq; i++ { 870 <-gotReqCh 871 } 872 873 nhigh := runtime.NumGoroutine() 874 875 // Tell all handlers to unblock and reply. 876 for i := 0; i < numReq; i++ { 877 unblockCh <- true 878 } 879 880 // Wait for all HTTP clients to be done. 881 for i := 0; i < numReq; i++ { 882 <-didReqCh 883 } 884 885 tr.CloseIdleConnections() 886 time.Sleep(100 * time.Millisecond) 887 runtime.GC() 888 runtime.GC() // even more. 889 nfinal := runtime.NumGoroutine() 890 891 growth := nfinal - n0 892 893 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 894 // Previously we were leaking one per numReq. 895 if int(growth) > 5 { 896 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 897 t.Error("too many new goroutines") 898 } 899 } 900 901 // golang.org/issue/4531: Transport leaks goroutines when 902 // request.ContentLength is explicitly short 903 func TestTransportPersistConnLeakShortBody(t *testing.T) { 904 if runtime.GOOS == "plan9" { 905 t.Skip("skipping test; see http://golang.org/issue/7237") 906 } 907 defer afterTest(t) 908 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 909 })) 910 defer ts.Close() 911 912 tr := &Transport{} 913 c := &Client{Transport: tr} 914 915 n0 := runtime.NumGoroutine() 916 body := []byte("Hello") 917 for i := 0; i < 20; i++ { 918 req, err := NewRequest("POST", ts.URL, bytes.NewReader(body)) 919 if err != nil { 920 t.Fatal(err) 921 } 922 req.ContentLength = int64(len(body) - 2) // explicitly short 923 _, err = c.Do(req) 924 if err == nil { 925 t.Fatal("Expect an error from writing too long of a body.") 926 } 927 } 928 nhigh := runtime.NumGoroutine() 929 tr.CloseIdleConnections() 930 time.Sleep(400 * time.Millisecond) 931 runtime.GC() 932 nfinal := runtime.NumGoroutine() 933 934 growth := nfinal - n0 935 936 // We expect 0 or 1 extra goroutine, empirically. Allow up to 5. 937 // Previously we were leaking one per numReq. 938 t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth) 939 if int(growth) > 5 { 940 t.Error("too many new goroutines") 941 } 942 } 943 944 // This used to crash; http://golang.org/issue/3266 945 func TestTransportIdleConnCrash(t *testing.T) { 946 defer afterTest(t) 947 tr := &Transport{} 948 c := &Client{Transport: tr} 949 950 unblockCh := make(chan bool, 1) 951 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 952 <-unblockCh 953 tr.CloseIdleConnections() 954 })) 955 defer ts.Close() 956 957 didreq := make(chan bool) 958 go func() { 959 res, err := c.Get(ts.URL) 960 if err != nil { 961 t.Error(err) 962 } else { 963 res.Body.Close() // returns idle conn 964 } 965 didreq <- true 966 }() 967 unblockCh <- true 968 <-didreq 969 } 970 971 // Test that the transport doesn't close the TCP connection early, 972 // before the response body has been read. This was a regression 973 // which sadly lacked a triggering test. The large response body made 974 // the old race easier to trigger. 975 func TestIssue3644(t *testing.T) { 976 defer afterTest(t) 977 const numFoos = 5000 978 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 979 w.Header().Set("Connection", "close") 980 for i := 0; i < numFoos; i++ { 981 w.Write([]byte("foo ")) 982 } 983 })) 984 defer ts.Close() 985 tr := &Transport{} 986 c := &Client{Transport: tr} 987 res, err := c.Get(ts.URL) 988 if err != nil { 989 t.Fatal(err) 990 } 991 defer res.Body.Close() 992 bs, err := ioutil.ReadAll(res.Body) 993 if err != nil { 994 t.Fatal(err) 995 } 996 if len(bs) != numFoos*len("foo ") { 997 t.Errorf("unexpected response length") 998 } 999 } 1000 1001 // Test that a client receives a server's reply, even if the server doesn't read 1002 // the entire request body. 1003 func TestIssue3595(t *testing.T) { 1004 defer afterTest(t) 1005 const deniedMsg = "sorry, denied." 1006 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1007 Error(w, deniedMsg, StatusUnauthorized) 1008 })) 1009 defer ts.Close() 1010 tr := &Transport{} 1011 c := &Client{Transport: tr} 1012 res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a')) 1013 if err != nil { 1014 t.Errorf("Post: %v", err) 1015 return 1016 } 1017 got, err := ioutil.ReadAll(res.Body) 1018 if err != nil { 1019 t.Fatalf("Body ReadAll: %v", err) 1020 } 1021 if !strings.Contains(string(got), deniedMsg) { 1022 t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg) 1023 } 1024 } 1025 1026 // From http://golang.org/issue/4454 , 1027 // "client fails to handle requests with no body and chunked encoding" 1028 func TestChunkedNoContent(t *testing.T) { 1029 defer afterTest(t) 1030 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1031 w.WriteHeader(StatusNoContent) 1032 })) 1033 defer ts.Close() 1034 1035 for _, closeBody := range []bool{true, false} { 1036 c := &Client{Transport: &Transport{}} 1037 const n = 4 1038 for i := 1; i <= n; i++ { 1039 res, err := c.Get(ts.URL) 1040 if err != nil { 1041 t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err) 1042 } else { 1043 if closeBody { 1044 res.Body.Close() 1045 } 1046 } 1047 } 1048 } 1049 } 1050 1051 func TestTransportConcurrency(t *testing.T) { 1052 defer afterTest(t) 1053 maxProcs, numReqs := 16, 500 1054 if testing.Short() { 1055 maxProcs, numReqs = 4, 50 1056 } 1057 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1058 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1059 fmt.Fprintf(w, "%v", r.FormValue("echo")) 1060 })) 1061 defer ts.Close() 1062 1063 var wg sync.WaitGroup 1064 wg.Add(numReqs) 1065 1066 // Due to the Transport's "socket late binding" (see 1067 // idleConnCh in transport.go), the numReqs HTTP requests 1068 // below can finish with a dial still outstanding. To keep 1069 // the leak checker happy, keep track of pending dials and 1070 // wait for them to finish (and be closed or returned to the 1071 // idle pool) before we close idle connections. 1072 SetPendingDialHooks(func() { wg.Add(1) }, wg.Done) 1073 defer SetPendingDialHooks(nil, nil) 1074 1075 tr := &Transport{} 1076 defer tr.CloseIdleConnections() 1077 1078 c := &Client{Transport: tr} 1079 reqs := make(chan string) 1080 defer close(reqs) 1081 1082 for i := 0; i < maxProcs*2; i++ { 1083 go func() { 1084 for req := range reqs { 1085 res, err := c.Get(ts.URL + "/?echo=" + req) 1086 if err != nil { 1087 t.Errorf("error on req %s: %v", req, err) 1088 wg.Done() 1089 continue 1090 } 1091 all, err := ioutil.ReadAll(res.Body) 1092 if err != nil { 1093 t.Errorf("read error on req %s: %v", req, err) 1094 wg.Done() 1095 continue 1096 } 1097 if string(all) != req { 1098 t.Errorf("body of req %s = %q; want %q", req, all, req) 1099 } 1100 res.Body.Close() 1101 wg.Done() 1102 } 1103 }() 1104 } 1105 for i := 0; i < numReqs; i++ { 1106 reqs <- fmt.Sprintf("request-%d", i) 1107 } 1108 wg.Wait() 1109 } 1110 1111 func TestIssue4191_InfiniteGetTimeout(t *testing.T) { 1112 if runtime.GOOS == "plan9" { 1113 t.Skip("skipping test; see http://golang.org/issue/7237") 1114 } 1115 defer afterTest(t) 1116 const debug = false 1117 mux := NewServeMux() 1118 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1119 io.Copy(w, neverEnding('a')) 1120 }) 1121 ts := httptest.NewServer(mux) 1122 timeout := 100 * time.Millisecond 1123 1124 client := &Client{ 1125 Transport: &Transport{ 1126 Dial: func(n, addr string) (net.Conn, error) { 1127 conn, err := net.Dial(n, addr) 1128 if err != nil { 1129 return nil, err 1130 } 1131 conn.SetDeadline(time.Now().Add(timeout)) 1132 if debug { 1133 conn = NewLoggingConn("client", conn) 1134 } 1135 return conn, nil 1136 }, 1137 DisableKeepAlives: true, 1138 }, 1139 } 1140 1141 getFailed := false 1142 nRuns := 5 1143 if testing.Short() { 1144 nRuns = 1 1145 } 1146 for i := 0; i < nRuns; i++ { 1147 if debug { 1148 println("run", i+1, "of", nRuns) 1149 } 1150 sres, err := client.Get(ts.URL + "/get") 1151 if err != nil { 1152 if !getFailed { 1153 // Make the timeout longer, once. 1154 getFailed = true 1155 t.Logf("increasing timeout") 1156 i-- 1157 timeout *= 10 1158 continue 1159 } 1160 t.Errorf("Error issuing GET: %v", err) 1161 break 1162 } 1163 _, err = io.Copy(ioutil.Discard, sres.Body) 1164 if err == nil { 1165 t.Errorf("Unexpected successful copy") 1166 break 1167 } 1168 } 1169 if debug { 1170 println("tests complete; waiting for handlers to finish") 1171 } 1172 ts.Close() 1173 } 1174 1175 func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) { 1176 if runtime.GOOS == "plan9" { 1177 t.Skip("skipping test; see http://golang.org/issue/7237") 1178 } 1179 defer afterTest(t) 1180 const debug = false 1181 mux := NewServeMux() 1182 mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { 1183 io.Copy(w, neverEnding('a')) 1184 }) 1185 mux.HandleFunc("/put", func(w ResponseWriter, r *Request) { 1186 defer r.Body.Close() 1187 io.Copy(ioutil.Discard, r.Body) 1188 }) 1189 ts := httptest.NewServer(mux) 1190 timeout := 100 * time.Millisecond 1191 1192 client := &Client{ 1193 Transport: &Transport{ 1194 Dial: func(n, addr string) (net.Conn, error) { 1195 conn, err := net.Dial(n, addr) 1196 if err != nil { 1197 return nil, err 1198 } 1199 conn.SetDeadline(time.Now().Add(timeout)) 1200 if debug { 1201 conn = NewLoggingConn("client", conn) 1202 } 1203 return conn, nil 1204 }, 1205 DisableKeepAlives: true, 1206 }, 1207 } 1208 1209 getFailed := false 1210 nRuns := 5 1211 if testing.Short() { 1212 nRuns = 1 1213 } 1214 for i := 0; i < nRuns; i++ { 1215 if debug { 1216 println("run", i+1, "of", nRuns) 1217 } 1218 sres, err := client.Get(ts.URL + "/get") 1219 if err != nil { 1220 if !getFailed { 1221 // Make the timeout longer, once. 1222 getFailed = true 1223 t.Logf("increasing timeout") 1224 i-- 1225 timeout *= 10 1226 continue 1227 } 1228 t.Errorf("Error issuing GET: %v", err) 1229 break 1230 } 1231 req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body) 1232 _, err = client.Do(req) 1233 if err == nil { 1234 sres.Body.Close() 1235 t.Errorf("Unexpected successful PUT") 1236 break 1237 } 1238 sres.Body.Close() 1239 } 1240 if debug { 1241 println("tests complete; waiting for handlers to finish") 1242 } 1243 ts.Close() 1244 } 1245 1246 func TestTransportResponseHeaderTimeout(t *testing.T) { 1247 defer afterTest(t) 1248 if testing.Short() { 1249 t.Skip("skipping timeout test in -short mode") 1250 } 1251 inHandler := make(chan bool, 1) 1252 mux := NewServeMux() 1253 mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) { 1254 inHandler <- true 1255 }) 1256 mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) { 1257 inHandler <- true 1258 time.Sleep(2 * time.Second) 1259 }) 1260 ts := httptest.NewServer(mux) 1261 defer ts.Close() 1262 1263 tr := &Transport{ 1264 ResponseHeaderTimeout: 500 * time.Millisecond, 1265 } 1266 defer tr.CloseIdleConnections() 1267 c := &Client{Transport: tr} 1268 1269 tests := []struct { 1270 path string 1271 want int 1272 wantErr string 1273 }{ 1274 {path: "/fast", want: 200}, 1275 {path: "/slow", wantErr: "timeout awaiting response headers"}, 1276 {path: "/fast", want: 200}, 1277 } 1278 for i, tt := range tests { 1279 res, err := c.Get(ts.URL + tt.path) 1280 select { 1281 case <-inHandler: 1282 case <-time.After(5 * time.Second): 1283 t.Errorf("never entered handler for test index %d, %s", i, tt.path) 1284 continue 1285 } 1286 if err != nil { 1287 uerr, ok := err.(*url.Error) 1288 if !ok { 1289 t.Errorf("error is not an url.Error; got: %#v", err) 1290 continue 1291 } 1292 nerr, ok := uerr.Err.(net.Error) 1293 if !ok { 1294 t.Errorf("error does not satisfy net.Error interface; got: %#v", err) 1295 continue 1296 } 1297 if !nerr.Timeout() { 1298 t.Errorf("want timeout error; got: %q", nerr) 1299 continue 1300 } 1301 if strings.Contains(err.Error(), tt.wantErr) { 1302 continue 1303 } 1304 t.Errorf("%d. unexpected error: %v", i, err) 1305 continue 1306 } 1307 if tt.wantErr != "" { 1308 t.Errorf("%d. no error. expected error: %v", i, tt.wantErr) 1309 continue 1310 } 1311 if res.StatusCode != tt.want { 1312 t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want) 1313 } 1314 } 1315 } 1316 1317 func TestTransportCancelRequest(t *testing.T) { 1318 defer afterTest(t) 1319 if testing.Short() { 1320 t.Skip("skipping test in -short mode") 1321 } 1322 unblockc := make(chan bool) 1323 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1324 fmt.Fprintf(w, "Hello") 1325 w.(Flusher).Flush() // send headers and some body 1326 <-unblockc 1327 })) 1328 defer ts.Close() 1329 defer close(unblockc) 1330 1331 tr := &Transport{} 1332 defer tr.CloseIdleConnections() 1333 c := &Client{Transport: tr} 1334 1335 req, _ := NewRequest("GET", ts.URL, nil) 1336 res, err := c.Do(req) 1337 if err != nil { 1338 t.Fatal(err) 1339 } 1340 go func() { 1341 time.Sleep(1 * time.Second) 1342 tr.CancelRequest(req) 1343 }() 1344 t0 := time.Now() 1345 body, err := ioutil.ReadAll(res.Body) 1346 d := time.Since(t0) 1347 1348 if err == nil { 1349 t.Error("expected an error reading the body") 1350 } 1351 if string(body) != "Hello" { 1352 t.Errorf("Body = %q; want Hello", body) 1353 } 1354 if d < 500*time.Millisecond { 1355 t.Errorf("expected ~1 second delay; got %v", d) 1356 } 1357 // Verify no outstanding requests after readLoop/writeLoop 1358 // goroutines shut down. 1359 for tries := 3; tries > 0; tries-- { 1360 n := tr.NumPendingRequestsForTesting() 1361 if n == 0 { 1362 break 1363 } 1364 time.Sleep(100 * time.Millisecond) 1365 if tries == 1 { 1366 t.Errorf("pending requests = %d; want 0", n) 1367 } 1368 } 1369 } 1370 1371 func TestTransportCancelRequestInDial(t *testing.T) { 1372 defer afterTest(t) 1373 if testing.Short() { 1374 t.Skip("skipping test in -short mode") 1375 } 1376 var logbuf bytes.Buffer 1377 eventLog := log.New(&logbuf, "", 0) 1378 1379 unblockDial := make(chan bool) 1380 defer close(unblockDial) 1381 1382 inDial := make(chan bool) 1383 tr := &Transport{ 1384 Dial: func(network, addr string) (net.Conn, error) { 1385 eventLog.Println("dial: blocking") 1386 inDial <- true 1387 <-unblockDial 1388 return nil, errors.New("nope") 1389 }, 1390 } 1391 cl := &Client{Transport: tr} 1392 gotres := make(chan bool) 1393 req, _ := NewRequest("GET", "http://something.no-network.tld/", nil) 1394 go func() { 1395 _, err := cl.Do(req) 1396 eventLog.Printf("Get = %v", err) 1397 gotres <- true 1398 }() 1399 1400 select { 1401 case <-inDial: 1402 case <-time.After(5 * time.Second): 1403 t.Fatal("timeout; never saw blocking dial") 1404 } 1405 1406 eventLog.Printf("canceling") 1407 tr.CancelRequest(req) 1408 1409 select { 1410 case <-gotres: 1411 case <-time.After(5 * time.Second): 1412 panic("hang. events are: " + logbuf.String()) 1413 } 1414 1415 got := logbuf.String() 1416 want := `dial: blocking 1417 canceling 1418 Get = Get http://something.no-network.tld/: net/http: request canceled while waiting for connection 1419 ` 1420 if got != want { 1421 t.Errorf("Got events:\n%s\nWant:\n%s", got, want) 1422 } 1423 } 1424 1425 // golang.org/issue/3672 -- Client can't close HTTP stream 1426 // Calling Close on a Response.Body used to just read until EOF. 1427 // Now it actually closes the TCP connection. 1428 func TestTransportCloseResponseBody(t *testing.T) { 1429 defer afterTest(t) 1430 writeErr := make(chan error, 1) 1431 msg := []byte("young\n") 1432 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1433 for { 1434 _, err := w.Write(msg) 1435 if err != nil { 1436 writeErr <- err 1437 return 1438 } 1439 w.(Flusher).Flush() 1440 } 1441 })) 1442 defer ts.Close() 1443 1444 tr := &Transport{} 1445 defer tr.CloseIdleConnections() 1446 c := &Client{Transport: tr} 1447 1448 req, _ := NewRequest("GET", ts.URL, nil) 1449 defer tr.CancelRequest(req) 1450 1451 res, err := c.Do(req) 1452 if err != nil { 1453 t.Fatal(err) 1454 } 1455 1456 const repeats = 3 1457 buf := make([]byte, len(msg)*repeats) 1458 want := bytes.Repeat(msg, repeats) 1459 1460 _, err = io.ReadFull(res.Body, buf) 1461 if err != nil { 1462 t.Fatal(err) 1463 } 1464 if !bytes.Equal(buf, want) { 1465 t.Fatalf("read %q; want %q", buf, want) 1466 } 1467 didClose := make(chan error, 1) 1468 go func() { 1469 didClose <- res.Body.Close() 1470 }() 1471 select { 1472 case err := <-didClose: 1473 if err != nil { 1474 t.Errorf("Close = %v", err) 1475 } 1476 case <-time.After(10 * time.Second): 1477 t.Fatal("too long waiting for close") 1478 } 1479 select { 1480 case err := <-writeErr: 1481 if err == nil { 1482 t.Errorf("expected non-nil write error") 1483 } 1484 case <-time.After(10 * time.Second): 1485 t.Fatal("too long waiting for write error") 1486 } 1487 } 1488 1489 type fooProto struct{} 1490 1491 func (fooProto) RoundTrip(req *Request) (*Response, error) { 1492 res := &Response{ 1493 Status: "200 OK", 1494 StatusCode: 200, 1495 Header: make(Header), 1496 Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())), 1497 } 1498 return res, nil 1499 } 1500 1501 func TestTransportAltProto(t *testing.T) { 1502 defer afterTest(t) 1503 tr := &Transport{} 1504 c := &Client{Transport: tr} 1505 tr.RegisterProtocol("foo", fooProto{}) 1506 res, err := c.Get("foo://bar.com/path") 1507 if err != nil { 1508 t.Fatal(err) 1509 } 1510 bodyb, err := ioutil.ReadAll(res.Body) 1511 if err != nil { 1512 t.Fatal(err) 1513 } 1514 body := string(bodyb) 1515 if e := "You wanted foo://bar.com/path"; body != e { 1516 t.Errorf("got response %q, want %q", body, e) 1517 } 1518 } 1519 1520 func TestTransportNoHost(t *testing.T) { 1521 defer afterTest(t) 1522 tr := &Transport{} 1523 _, err := tr.RoundTrip(&Request{ 1524 Header: make(Header), 1525 URL: &url.URL{ 1526 Scheme: "http", 1527 }, 1528 }) 1529 want := "http: no Host in request URL" 1530 if got := fmt.Sprint(err); got != want { 1531 t.Errorf("error = %v; want %q", err, want) 1532 } 1533 } 1534 1535 func TestTransportSocketLateBinding(t *testing.T) { 1536 defer afterTest(t) 1537 1538 mux := NewServeMux() 1539 fooGate := make(chan bool, 1) 1540 mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) { 1541 w.Header().Set("foo-ipport", r.RemoteAddr) 1542 w.(Flusher).Flush() 1543 <-fooGate 1544 }) 1545 mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) { 1546 w.Header().Set("bar-ipport", r.RemoteAddr) 1547 }) 1548 ts := httptest.NewServer(mux) 1549 defer ts.Close() 1550 1551 dialGate := make(chan bool, 1) 1552 tr := &Transport{ 1553 Dial: func(n, addr string) (net.Conn, error) { 1554 if <-dialGate { 1555 return net.Dial(n, addr) 1556 } 1557 return nil, errors.New("manually closed") 1558 }, 1559 DisableKeepAlives: false, 1560 } 1561 defer tr.CloseIdleConnections() 1562 c := &Client{ 1563 Transport: tr, 1564 } 1565 1566 dialGate <- true // only allow one dial 1567 fooRes, err := c.Get(ts.URL + "/foo") 1568 if err != nil { 1569 t.Fatal(err) 1570 } 1571 fooAddr := fooRes.Header.Get("foo-ipport") 1572 if fooAddr == "" { 1573 t.Fatal("No addr on /foo request") 1574 } 1575 time.AfterFunc(200*time.Millisecond, func() { 1576 // let the foo response finish so we can use its 1577 // connection for /bar 1578 fooGate <- true 1579 io.Copy(ioutil.Discard, fooRes.Body) 1580 fooRes.Body.Close() 1581 }) 1582 1583 barRes, err := c.Get(ts.URL + "/bar") 1584 if err != nil { 1585 t.Fatal(err) 1586 } 1587 barAddr := barRes.Header.Get("bar-ipport") 1588 if barAddr != fooAddr { 1589 t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr) 1590 } 1591 barRes.Body.Close() 1592 dialGate <- false 1593 } 1594 1595 // Issue 2184 1596 func TestTransportReading100Continue(t *testing.T) { 1597 defer afterTest(t) 1598 1599 const numReqs = 5 1600 reqBody := func(n int) string { return fmt.Sprintf("request body %d", n) } 1601 reqID := func(n int) string { return fmt.Sprintf("REQ-ID-%d", n) } 1602 1603 send100Response := func(w *io.PipeWriter, r *io.PipeReader) { 1604 defer w.Close() 1605 defer r.Close() 1606 br := bufio.NewReader(r) 1607 n := 0 1608 for { 1609 n++ 1610 req, err := ReadRequest(br) 1611 if err == io.EOF { 1612 return 1613 } 1614 if err != nil { 1615 t.Error(err) 1616 return 1617 } 1618 slurp, err := ioutil.ReadAll(req.Body) 1619 if err != nil { 1620 t.Errorf("Server request body slurp: %v", err) 1621 return 1622 } 1623 id := req.Header.Get("Request-Id") 1624 resCode := req.Header.Get("X-Want-Response-Code") 1625 if resCode == "" { 1626 resCode = "100 Continue" 1627 if string(slurp) != reqBody(n) { 1628 t.Errorf("Server got %q, %v; want %q", slurp, err, reqBody(n)) 1629 } 1630 } 1631 body := fmt.Sprintf("Response number %d", n) 1632 v := []byte(strings.Replace(fmt.Sprintf(`HTTP/1.1 %s 1633 Date: Thu, 28 Feb 2013 17:55:41 GMT 1634 1635 HTTP/1.1 200 OK 1636 Content-Type: text/html 1637 Echo-Request-Id: %s 1638 Content-Length: %d 1639 1640 %s`, resCode, id, len(body), body), "\n", "\r\n", -1)) 1641 w.Write(v) 1642 if id == reqID(numReqs) { 1643 return 1644 } 1645 } 1646 1647 } 1648 1649 tr := &Transport{ 1650 Dial: func(n, addr string) (net.Conn, error) { 1651 sr, sw := io.Pipe() // server read/write 1652 cr, cw := io.Pipe() // client read/write 1653 conn := &rwTestConn{ 1654 Reader: cr, 1655 Writer: sw, 1656 closeFunc: func() error { 1657 sw.Close() 1658 cw.Close() 1659 return nil 1660 }, 1661 } 1662 go send100Response(cw, sr) 1663 return conn, nil 1664 }, 1665 DisableKeepAlives: false, 1666 } 1667 defer tr.CloseIdleConnections() 1668 c := &Client{Transport: tr} 1669 1670 testResponse := func(req *Request, name string, wantCode int) { 1671 res, err := c.Do(req) 1672 if err != nil { 1673 t.Fatalf("%s: Do: %v", name, err) 1674 } 1675 if res.StatusCode != wantCode { 1676 t.Fatalf("%s: Response Statuscode=%d; want %d", name, res.StatusCode, wantCode) 1677 } 1678 if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack { 1679 t.Errorf("%s: response id %q != request id %q", name, idBack, id) 1680 } 1681 _, err = ioutil.ReadAll(res.Body) 1682 if err != nil { 1683 t.Fatalf("%s: Slurp error: %v", name, err) 1684 } 1685 } 1686 1687 // Few 100 responses, making sure we're not off-by-one. 1688 for i := 1; i <= numReqs; i++ { 1689 req, _ := NewRequest("POST", "http://dummy.tld/", strings.NewReader(reqBody(i))) 1690 req.Header.Set("Request-Id", reqID(i)) 1691 testResponse(req, fmt.Sprintf("100, %d/%d", i, numReqs), 200) 1692 } 1693 1694 // And some other informational 1xx but non-100 responses, to test 1695 // we return them but don't re-use the connection. 1696 for i := 1; i <= numReqs; i++ { 1697 req, _ := NewRequest("POST", "http://other.tld/", strings.NewReader(reqBody(i))) 1698 req.Header.Set("X-Want-Response-Code", "123 Sesame Street") 1699 testResponse(req, fmt.Sprintf("123, %d/%d", i, numReqs), 123) 1700 } 1701 } 1702 1703 type proxyFromEnvTest struct { 1704 req string // URL to fetch; blank means "http://example.com" 1705 1706 env string // HTTP_PROXY 1707 httpsenv string // HTTPS_PROXY 1708 noenv string // NO_RPXY 1709 1710 want string 1711 wanterr error 1712 } 1713 1714 func (t proxyFromEnvTest) String() string { 1715 var buf bytes.Buffer 1716 space := func() { 1717 if buf.Len() > 0 { 1718 buf.WriteByte(' ') 1719 } 1720 } 1721 if t.env != "" { 1722 fmt.Fprintf(&buf, "http_proxy=%q", t.env) 1723 } 1724 if t.httpsenv != "" { 1725 space() 1726 fmt.Fprintf(&buf, "https_proxy=%q", t.httpsenv) 1727 } 1728 if t.noenv != "" { 1729 space() 1730 fmt.Fprintf(&buf, "no_proxy=%q", t.noenv) 1731 } 1732 req := "http://example.com" 1733 if t.req != "" { 1734 req = t.req 1735 } 1736 space() 1737 fmt.Fprintf(&buf, "req=%q", req) 1738 return strings.TrimSpace(buf.String()) 1739 } 1740 1741 var proxyFromEnvTests = []proxyFromEnvTest{ 1742 {env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 1743 {env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"}, 1744 {env: "cache.corp.example.com", want: "http://cache.corp.example.com"}, 1745 {env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"}, 1746 {env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"}, 1747 {env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"}, 1748 1749 // Don't use secure for http 1750 {req: "http://insecure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://http.proxy.tld"}, 1751 // Use secure for https. 1752 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"}, 1753 {req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"}, 1754 1755 {want: "<nil>"}, 1756 1757 {noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 1758 {noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"}, 1759 {noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 1760 {noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"}, 1761 {noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"}, 1762 } 1763 1764 func TestProxyFromEnvironment(t *testing.T) { 1765 ResetProxyEnv() 1766 for _, tt := range proxyFromEnvTests { 1767 os.Setenv("HTTP_PROXY", tt.env) 1768 os.Setenv("HTTPS_PROXY", tt.httpsenv) 1769 os.Setenv("NO_PROXY", tt.noenv) 1770 ResetCachedEnvironment() 1771 reqURL := tt.req 1772 if reqURL == "" { 1773 reqURL = "http://example.com" 1774 } 1775 req, _ := NewRequest("GET", reqURL, nil) 1776 url, err := ProxyFromEnvironment(req) 1777 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 1778 t.Errorf("%v: got error = %q, want %q", tt, g, e) 1779 continue 1780 } 1781 if got := fmt.Sprintf("%s", url); got != tt.want { 1782 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 1783 } 1784 } 1785 } 1786 1787 func TestIdleConnChannelLeak(t *testing.T) { 1788 var mu sync.Mutex 1789 var n int 1790 1791 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1792 mu.Lock() 1793 n++ 1794 mu.Unlock() 1795 })) 1796 defer ts.Close() 1797 1798 tr := &Transport{ 1799 Dial: func(netw, addr string) (net.Conn, error) { 1800 return net.Dial(netw, ts.Listener.Addr().String()) 1801 }, 1802 } 1803 defer tr.CloseIdleConnections() 1804 1805 c := &Client{Transport: tr} 1806 1807 // First, without keep-alives. 1808 for _, disableKeep := range []bool{true, false} { 1809 tr.DisableKeepAlives = disableKeep 1810 for i := 0; i < 5; i++ { 1811 _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i)) 1812 if err != nil { 1813 t.Fatal(err) 1814 } 1815 } 1816 if got := tr.IdleConnChMapSizeForTesting(); got != 0 { 1817 t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got) 1818 } 1819 } 1820 } 1821 1822 // Verify the status quo: that the Client.Post function coerces its 1823 // body into a ReadCloser if it's a Closer, and that the Transport 1824 // then closes it. 1825 func TestTransportClosesRequestBody(t *testing.T) { 1826 defer afterTest(t) 1827 ts := httptest.NewServer(http.HandlerFunc(func(w ResponseWriter, r *Request) { 1828 io.Copy(ioutil.Discard, r.Body) 1829 })) 1830 defer ts.Close() 1831 1832 tr := &Transport{} 1833 defer tr.CloseIdleConnections() 1834 cl := &Client{Transport: tr} 1835 1836 closes := 0 1837 1838 res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")}) 1839 if err != nil { 1840 t.Fatal(err) 1841 } 1842 res.Body.Close() 1843 if closes != 1 { 1844 t.Errorf("closes = %d; want 1", closes) 1845 } 1846 } 1847 1848 func TestTransportTLSHandshakeTimeout(t *testing.T) { 1849 defer afterTest(t) 1850 if testing.Short() { 1851 t.Skip("skipping in short mode") 1852 } 1853 ln := newLocalListener(t) 1854 defer ln.Close() 1855 testdonec := make(chan struct{}) 1856 defer close(testdonec) 1857 1858 go func() { 1859 c, err := ln.Accept() 1860 if err != nil { 1861 t.Error(err) 1862 return 1863 } 1864 <-testdonec 1865 c.Close() 1866 }() 1867 1868 getdonec := make(chan struct{}) 1869 go func() { 1870 defer close(getdonec) 1871 tr := &Transport{ 1872 Dial: func(_, _ string) (net.Conn, error) { 1873 return net.Dial("tcp", ln.Addr().String()) 1874 }, 1875 TLSHandshakeTimeout: 250 * time.Millisecond, 1876 } 1877 cl := &Client{Transport: tr} 1878 _, err := cl.Get("https://dummy.tld/") 1879 if err == nil { 1880 t.Error("expected error") 1881 return 1882 } 1883 ue, ok := err.(*url.Error) 1884 if !ok { 1885 t.Errorf("expected url.Error; got %#v", err) 1886 return 1887 } 1888 ne, ok := ue.Err.(net.Error) 1889 if !ok { 1890 t.Errorf("expected net.Error; got %#v", err) 1891 return 1892 } 1893 if !ne.Timeout() { 1894 t.Errorf("expected timeout error; got %v", err) 1895 } 1896 if !strings.Contains(err.Error(), "handshake timeout") { 1897 t.Errorf("expected 'handshake timeout' in error; got %v", err) 1898 } 1899 }() 1900 select { 1901 case <-getdonec: 1902 case <-time.After(5 * time.Second): 1903 t.Error("test timeout; TLS handshake hung?") 1904 } 1905 } 1906 1907 // Trying to repro golang.org/issue/3514 1908 func TestTLSServerClosesConnection(t *testing.T) { 1909 defer afterTest(t) 1910 if runtime.GOOS == "windows" { 1911 t.Skip("skipping flaky test on Windows; golang.org/issue/7634") 1912 } 1913 closedc := make(chan bool, 1) 1914 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1915 if strings.Contains(r.URL.Path, "/keep-alive-then-die") { 1916 conn, _, _ := w.(Hijacker).Hijack() 1917 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) 1918 conn.Close() 1919 closedc <- true 1920 return 1921 } 1922 fmt.Fprintf(w, "hello") 1923 })) 1924 defer ts.Close() 1925 tr := &Transport{ 1926 TLSClientConfig: &tls.Config{ 1927 InsecureSkipVerify: true, 1928 }, 1929 } 1930 defer tr.CloseIdleConnections() 1931 client := &Client{Transport: tr} 1932 1933 var nSuccess = 0 1934 var errs []error 1935 const trials = 20 1936 for i := 0; i < trials; i++ { 1937 tr.CloseIdleConnections() 1938 res, err := client.Get(ts.URL + "/keep-alive-then-die") 1939 if err != nil { 1940 t.Fatal(err) 1941 } 1942 <-closedc 1943 slurp, err := ioutil.ReadAll(res.Body) 1944 if err != nil { 1945 t.Fatal(err) 1946 } 1947 if string(slurp) != "foo" { 1948 t.Errorf("Got %q, want foo", slurp) 1949 } 1950 1951 // The underlying m-thread scheduler on akaros thread is cooperative, 1952 // so we introduce this voluntary yield to make sure that the go 1953 // routine reading EOF off the network gets a chance to run before 1954 // moving on to the call below. 1955 if runtime.GOOS == "akaros" { 1956 runtime.Gosched() 1957 } 1958 1959 // Now try again and see if we successfully 1960 // pick a new connection. 1961 res, err = client.Get(ts.URL + "/") 1962 if err != nil { 1963 errs = append(errs, err) 1964 continue 1965 } 1966 slurp, err = ioutil.ReadAll(res.Body) 1967 if err != nil { 1968 errs = append(errs, err) 1969 continue 1970 } 1971 nSuccess++ 1972 } 1973 if nSuccess > 0 { 1974 t.Logf("successes = %d of %d", nSuccess, trials) 1975 } else { 1976 t.Errorf("All runs failed:") 1977 } 1978 for _, err := range errs { 1979 t.Logf(" err: %v", err) 1980 } 1981 } 1982 1983 // byteFromChanReader is an io.Reader that reads a single byte at a 1984 // time from the channel. When the channel is closed, the reader 1985 // returns io.EOF. 1986 type byteFromChanReader chan byte 1987 1988 func (c byteFromChanReader) Read(p []byte) (n int, err error) { 1989 if len(p) == 0 { 1990 return 1991 } 1992 b, ok := <-c 1993 if !ok { 1994 return 0, io.EOF 1995 } 1996 p[0] = b 1997 return 1, nil 1998 } 1999 2000 // Verifies that the Transport doesn't reuse a connection in the case 2001 // where the server replies before the request has been fully 2002 // written. We still honor that reply (see TestIssue3595), but don't 2003 // send future requests on the connection because it's then in a 2004 // questionable state. 2005 // golang.org/issue/7569 2006 func TestTransportNoReuseAfterEarlyResponse(t *testing.T) { 2007 defer afterTest(t) 2008 var sconn struct { 2009 sync.Mutex 2010 c net.Conn 2011 } 2012 var getOkay bool 2013 closeConn := func() { 2014 sconn.Lock() 2015 defer sconn.Unlock() 2016 if sconn.c != nil { 2017 sconn.c.Close() 2018 sconn.c = nil 2019 if !getOkay { 2020 t.Logf("Closed server connection") 2021 } 2022 } 2023 } 2024 defer closeConn() 2025 2026 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2027 if r.Method == "GET" { 2028 io.WriteString(w, "bar") 2029 return 2030 } 2031 conn, _, _ := w.(Hijacker).Hijack() 2032 sconn.Lock() 2033 sconn.c = conn 2034 sconn.Unlock() 2035 conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive 2036 go io.Copy(ioutil.Discard, conn) 2037 })) 2038 defer ts.Close() 2039 tr := &Transport{} 2040 defer tr.CloseIdleConnections() 2041 client := &Client{Transport: tr} 2042 2043 const bodySize = 256 << 10 2044 finalBit := make(byteFromChanReader, 1) 2045 req, _ := NewRequest("POST", ts.URL, io.MultiReader(io.LimitReader(neverEnding('x'), bodySize-1), finalBit)) 2046 req.ContentLength = bodySize 2047 res, err := client.Do(req) 2048 if err := wantBody(res, err, "foo"); err != nil { 2049 t.Errorf("POST response: %v", err) 2050 } 2051 donec := make(chan bool) 2052 go func() { 2053 defer close(donec) 2054 res, err = client.Get(ts.URL) 2055 if err := wantBody(res, err, "bar"); err != nil { 2056 t.Errorf("GET response: %v", err) 2057 return 2058 } 2059 getOkay = true // suppress test noise 2060 }() 2061 time.AfterFunc(5*time.Second, closeConn) 2062 select { 2063 case <-donec: 2064 finalBit <- 'x' // unblock the writeloop of the first Post 2065 close(finalBit) 2066 case <-time.After(7 * time.Second): 2067 t.Fatal("timeout waiting for GET request to finish") 2068 } 2069 } 2070 2071 type errorReader struct { 2072 err error 2073 } 2074 2075 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err } 2076 2077 type closerFunc func() error 2078 2079 func (f closerFunc) Close() error { return f() } 2080 2081 // Issue 6981 2082 func TestTransportClosesBodyOnError(t *testing.T) { 2083 if runtime.GOOS == "plan9" { 2084 t.Skip("skipping test; see http://golang.org/issue/7782") 2085 } 2086 defer afterTest(t) 2087 readBody := make(chan error, 1) 2088 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2089 _, err := ioutil.ReadAll(r.Body) 2090 readBody <- err 2091 })) 2092 defer ts.Close() 2093 fakeErr := errors.New("fake error") 2094 didClose := make(chan bool, 1) 2095 req, _ := NewRequest("POST", ts.URL, struct { 2096 io.Reader 2097 io.Closer 2098 }{ 2099 io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}), 2100 closerFunc(func() error { 2101 select { 2102 case didClose <- true: 2103 default: 2104 } 2105 return nil 2106 }), 2107 }) 2108 res, err := DefaultClient.Do(req) 2109 if res != nil { 2110 defer res.Body.Close() 2111 } 2112 if err == nil || !strings.Contains(err.Error(), fakeErr.Error()) { 2113 t.Fatalf("Do error = %v; want something containing %q", err, fakeErr.Error()) 2114 } 2115 select { 2116 case err := <-readBody: 2117 if err == nil { 2118 t.Errorf("Unexpected success reading request body from handler; want 'unexpected EOF reading trailer'") 2119 } 2120 case <-time.After(5 * time.Second): 2121 t.Error("timeout waiting for server handler to complete") 2122 } 2123 select { 2124 case <-didClose: 2125 default: 2126 t.Errorf("didn't see Body.Close") 2127 } 2128 } 2129 2130 func TestTransportDialTLS(t *testing.T) { 2131 var mu sync.Mutex // guards following 2132 var gotReq, didDial bool 2133 2134 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2135 mu.Lock() 2136 gotReq = true 2137 mu.Unlock() 2138 })) 2139 defer ts.Close() 2140 tr := &Transport{ 2141 DialTLS: func(netw, addr string) (net.Conn, error) { 2142 mu.Lock() 2143 didDial = true 2144 mu.Unlock() 2145 c, err := tls.Dial(netw, addr, &tls.Config{ 2146 InsecureSkipVerify: true, 2147 }) 2148 if err != nil { 2149 return nil, err 2150 } 2151 return c, c.Handshake() 2152 }, 2153 } 2154 defer tr.CloseIdleConnections() 2155 client := &Client{Transport: tr} 2156 res, err := client.Get(ts.URL) 2157 if err != nil { 2158 t.Fatal(err) 2159 } 2160 res.Body.Close() 2161 mu.Lock() 2162 if !gotReq { 2163 t.Error("didn't get request") 2164 } 2165 if !didDial { 2166 t.Error("didn't use dial hook") 2167 } 2168 } 2169 2170 // Test for issue 8755 2171 // Ensure that if a proxy returns an error, it is exposed by RoundTrip 2172 func TestRoundTripReturnsProxyError(t *testing.T) { 2173 badProxy := func(*http.Request) (*url.URL, error) { 2174 return nil, errors.New("errorMessage") 2175 } 2176 2177 tr := &Transport{Proxy: badProxy} 2178 2179 req, _ := http.NewRequest("GET", "http://example.com", nil) 2180 2181 _, err := tr.RoundTrip(req) 2182 2183 if err == nil { 2184 t.Error("Expected proxy error to be returned by RoundTrip") 2185 } 2186 } 2187 2188 // tests that putting an idle conn after a call to CloseIdleConns does return it 2189 func TestTransportCloseIdleConnsThenReturn(t *testing.T) { 2190 tr := &Transport{} 2191 wantIdle := func(when string, n int) bool { 2192 got := tr.IdleConnCountForTesting("|http|example.com") // key used by PutIdleTestConn 2193 if got == n { 2194 return true 2195 } 2196 t.Errorf("%s: idle conns = %d; want %d", when, got, n) 2197 return false 2198 } 2199 wantIdle("start", 0) 2200 if !tr.PutIdleTestConn() { 2201 t.Fatal("put failed") 2202 } 2203 if !tr.PutIdleTestConn() { 2204 t.Fatal("second put failed") 2205 } 2206 wantIdle("after put", 2) 2207 tr.CloseIdleConnections() 2208 if !tr.IsIdleForTesting() { 2209 t.Error("should be idle after CloseIdleConnections") 2210 } 2211 wantIdle("after close idle", 0) 2212 if tr.PutIdleTestConn() { 2213 t.Fatal("put didn't fail") 2214 } 2215 wantIdle("after second put", 0) 2216 2217 tr.RequestIdleConnChForTesting() // should toggle the transport out of idle mode 2218 if tr.IsIdleForTesting() { 2219 t.Error("shouldn't be idle after RequestIdleConnChForTesting") 2220 } 2221 if !tr.PutIdleTestConn() { 2222 t.Fatal("after re-activation") 2223 } 2224 wantIdle("after final put", 1) 2225 } 2226 2227 // This tests that an client requesting a content range won't also 2228 // implicitly ask for gzip support. If they want that, they need to do it 2229 // on their own. 2230 // golang.org/issue/8923 2231 func TestTransportRangeAndGzip(t *testing.T) { 2232 defer afterTest(t) 2233 reqc := make(chan *Request, 1) 2234 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2235 reqc <- r 2236 })) 2237 defer ts.Close() 2238 2239 req, _ := NewRequest("GET", ts.URL, nil) 2240 req.Header.Set("Range", "bytes=7-11") 2241 res, err := DefaultClient.Do(req) 2242 if err != nil { 2243 t.Fatal(err) 2244 } 2245 2246 select { 2247 case r := <-reqc: 2248 if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { 2249 t.Error("Transport advertised gzip support in the Accept header") 2250 } 2251 if r.Header.Get("Range") == "" { 2252 t.Error("no Range in request") 2253 } 2254 case <-time.After(10 * time.Second): 2255 t.Fatal("timeout") 2256 } 2257 res.Body.Close() 2258 } 2259 2260 func wantBody(res *http.Response, err error, want string) error { 2261 if err != nil { 2262 return err 2263 } 2264 slurp, err := ioutil.ReadAll(res.Body) 2265 if err != nil { 2266 return fmt.Errorf("error reading body: %v", err) 2267 } 2268 if string(slurp) != want { 2269 return fmt.Errorf("body = %q; want %q", slurp, want) 2270 } 2271 if err := res.Body.Close(); err != nil { 2272 return fmt.Errorf("body Close = %v", err) 2273 } 2274 return nil 2275 } 2276 2277 func newLocalListener(t *testing.T) net.Listener { 2278 ln, err := net.Listen("tcp", "127.0.0.1:0") 2279 if err != nil { 2280 ln, err = net.Listen("tcp6", "[::1]:0") 2281 } 2282 if err != nil { 2283 t.Fatal(err) 2284 } 2285 return ln 2286 } 2287 2288 type countCloseReader struct { 2289 n *int 2290 io.Reader 2291 } 2292 2293 func (cr countCloseReader) Close() error { 2294 (*cr.n)++ 2295 return nil 2296 } 2297 2298 // rgz is a gzip quine that uncompresses to itself. 2299 var rgz = []byte{ 2300 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 2301 0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 2302 0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0, 2303 0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 2304 0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 2305 0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60, 2306 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2, 2307 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00, 2308 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 2309 0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16, 2310 0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05, 2311 0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff, 2312 0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00, 2313 0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 2314 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 2315 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 2316 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 2317 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 2318 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 2319 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 2320 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 2321 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff, 2322 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00, 2323 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 2324 0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 2325 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 2326 0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 2327 0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06, 2328 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00, 2329 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 2330 0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00, 2331 0x00, 0x00, 2332 }