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