1 // Copyright 2010 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 // End-to-end serving tests 6 7 package http_test 8 9 import ( 10 "bufio" 11 "bytes" 12 "crypto/tls" 13 "errors" 14 "fmt" 15 "io" 16 "io/ioutil" 17 "log" 18 "math/rand" 19 "net" 20 . "net/http" 21 "net/http/httptest" 22 "net/http/httputil" 23 "net/http/internal" 24 "net/url" 25 "os" 26 "os/exec" 27 "reflect" 28 "runtime" 29 "strconv" 30 "strings" 31 "sync" 32 "sync/atomic" 33 "syscall" 34 "testing" 35 "time" 36 ) 37 38 type dummyAddr string 39 type oneConnListener struct { 40 conn net.Conn 41 } 42 43 func (l *oneConnListener) Accept() (c net.Conn, err error) { 44 c = l.conn 45 if c == nil { 46 err = io.EOF 47 return 48 } 49 err = nil 50 l.conn = nil 51 return 52 } 53 54 func (l *oneConnListener) Close() error { 55 return nil 56 } 57 58 func (l *oneConnListener) Addr() net.Addr { 59 return dummyAddr("test-address") 60 } 61 62 func (a dummyAddr) Network() string { 63 return string(a) 64 } 65 66 func (a dummyAddr) String() string { 67 return string(a) 68 } 69 70 type noopConn struct{} 71 72 func (noopConn) LocalAddr() net.Addr { return dummyAddr("local-addr") } 73 func (noopConn) RemoteAddr() net.Addr { return dummyAddr("remote-addr") } 74 func (noopConn) SetDeadline(t time.Time) error { return nil } 75 func (noopConn) SetReadDeadline(t time.Time) error { return nil } 76 func (noopConn) SetWriteDeadline(t time.Time) error { return nil } 77 78 type rwTestConn struct { 79 io.Reader 80 io.Writer 81 noopConn 82 83 closeFunc func() error // called if non-nil 84 closec chan bool // else, if non-nil, send value to it on close 85 } 86 87 func (c *rwTestConn) Close() error { 88 if c.closeFunc != nil { 89 return c.closeFunc() 90 } 91 select { 92 case c.closec <- true: 93 default: 94 } 95 return nil 96 } 97 98 type testConn struct { 99 readBuf bytes.Buffer 100 writeBuf bytes.Buffer 101 closec chan bool // if non-nil, send value to it on close 102 noopConn 103 } 104 105 func (c *testConn) Read(b []byte) (int, error) { 106 return c.readBuf.Read(b) 107 } 108 109 func (c *testConn) Write(b []byte) (int, error) { 110 return c.writeBuf.Write(b) 111 } 112 113 func (c *testConn) Close() error { 114 select { 115 case c.closec <- true: 116 default: 117 } 118 return nil 119 } 120 121 // reqBytes treats req as a request (with \n delimiters) and returns it with \r\n delimiters, 122 // ending in \r\n\r\n 123 func reqBytes(req string) []byte { 124 return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n") 125 } 126 127 type handlerTest struct { 128 handler Handler 129 } 130 131 func newHandlerTest(h Handler) handlerTest { 132 return handlerTest{h} 133 } 134 135 func (ht handlerTest) rawResponse(req string) string { 136 reqb := reqBytes(req) 137 var output bytes.Buffer 138 conn := &rwTestConn{ 139 Reader: bytes.NewReader(reqb), 140 Writer: &output, 141 closec: make(chan bool, 1), 142 } 143 ln := &oneConnListener{conn: conn} 144 go Serve(ln, ht.handler) 145 <-conn.closec 146 return output.String() 147 } 148 149 func TestConsumingBodyOnNextConn(t *testing.T) { 150 defer afterTest(t) 151 conn := new(testConn) 152 for i := 0; i < 2; i++ { 153 conn.readBuf.Write([]byte( 154 "POST / HTTP/1.1\r\n" + 155 "Host: test\r\n" + 156 "Content-Length: 11\r\n" + 157 "\r\n" + 158 "foo=1&bar=1")) 159 } 160 161 reqNum := 0 162 ch := make(chan *Request) 163 servech := make(chan error) 164 listener := &oneConnListener{conn} 165 handler := func(res ResponseWriter, req *Request) { 166 reqNum++ 167 ch <- req 168 } 169 170 go func() { 171 servech <- Serve(listener, HandlerFunc(handler)) 172 }() 173 174 var req *Request 175 req = <-ch 176 if req == nil { 177 t.Fatal("Got nil first request.") 178 } 179 if req.Method != "POST" { 180 t.Errorf("For request #1's method, got %q; expected %q", 181 req.Method, "POST") 182 } 183 184 req = <-ch 185 if req == nil { 186 t.Fatal("Got nil first request.") 187 } 188 if req.Method != "POST" { 189 t.Errorf("For request #2's method, got %q; expected %q", 190 req.Method, "POST") 191 } 192 193 if serveerr := <-servech; serveerr != io.EOF { 194 t.Errorf("Serve returned %q; expected EOF", serveerr) 195 } 196 } 197 198 type stringHandler string 199 200 func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) { 201 w.Header().Set("Result", string(s)) 202 } 203 204 var handlers = []struct { 205 pattern string 206 msg string 207 }{ 208 {"/", "Default"}, 209 {"/someDir/", "someDir"}, 210 {"/#/", "hash"}, 211 {"someHost.com/someDir/", "someHost.com/someDir"}, 212 } 213 214 var vtests = []struct { 215 url string 216 expected string 217 }{ 218 {"http://localhost/someDir/apage", "someDir"}, 219 {"http://localhost/%23/apage", "hash"}, 220 {"http://localhost/otherDir/apage", "Default"}, 221 {"http://someHost.com/someDir/apage", "someHost.com/someDir"}, 222 {"http://otherHost.com/someDir/apage", "someDir"}, 223 {"http://otherHost.com/aDir/apage", "Default"}, 224 // redirections for trees 225 {"http://localhost/someDir", "/someDir/"}, 226 {"http://localhost/%23", "/%23/"}, 227 {"http://someHost.com/someDir", "/someDir/"}, 228 } 229 230 func TestHostHandlers(t *testing.T) { 231 defer afterTest(t) 232 mux := NewServeMux() 233 for _, h := range handlers { 234 mux.Handle(h.pattern, stringHandler(h.msg)) 235 } 236 ts := httptest.NewServer(mux) 237 defer ts.Close() 238 239 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 240 if err != nil { 241 t.Fatal(err) 242 } 243 defer conn.Close() 244 cc := httputil.NewClientConn(conn, nil) 245 for _, vt := range vtests { 246 var r *Response 247 var req Request 248 if req.URL, err = url.Parse(vt.url); err != nil { 249 t.Errorf("cannot parse url: %v", err) 250 continue 251 } 252 if err := cc.Write(&req); err != nil { 253 t.Errorf("writing request: %v", err) 254 continue 255 } 256 r, err := cc.Read(&req) 257 if err != nil { 258 t.Errorf("reading response: %v", err) 259 continue 260 } 261 switch r.StatusCode { 262 case StatusOK: 263 s := r.Header.Get("Result") 264 if s != vt.expected { 265 t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected) 266 } 267 case StatusMovedPermanently: 268 s := r.Header.Get("Location") 269 if s != vt.expected { 270 t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected) 271 } 272 default: 273 t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode) 274 } 275 } 276 } 277 278 var serveMuxRegister = []struct { 279 pattern string 280 h Handler 281 }{ 282 {"/dir/", serve(200)}, 283 {"/search", serve(201)}, 284 {"codesearch.google.com/search", serve(202)}, 285 {"codesearch.google.com/", serve(203)}, 286 {"example.com/", HandlerFunc(checkQueryStringHandler)}, 287 } 288 289 // serve returns a handler that sends a response with the given code. 290 func serve(code int) HandlerFunc { 291 return func(w ResponseWriter, r *Request) { 292 w.WriteHeader(code) 293 } 294 } 295 296 // checkQueryStringHandler checks if r.URL.RawQuery has the same value 297 // as the URL excluding the scheme and the query string and sends 200 298 // response code if it is, 500 otherwise. 299 func checkQueryStringHandler(w ResponseWriter, r *Request) { 300 u := *r.URL 301 u.Scheme = "http" 302 u.Host = r.Host 303 u.RawQuery = "" 304 if "http://"+r.URL.RawQuery == u.String() { 305 w.WriteHeader(200) 306 } else { 307 w.WriteHeader(500) 308 } 309 } 310 311 var serveMuxTests = []struct { 312 method string 313 host string 314 path string 315 code int 316 pattern string 317 }{ 318 {"GET", "google.com", "/", 404, ""}, 319 {"GET", "google.com", "/dir", 301, "/dir/"}, 320 {"GET", "google.com", "/dir/", 200, "/dir/"}, 321 {"GET", "google.com", "/dir/file", 200, "/dir/"}, 322 {"GET", "google.com", "/search", 201, "/search"}, 323 {"GET", "google.com", "/search/", 404, ""}, 324 {"GET", "google.com", "/search/foo", 404, ""}, 325 {"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"}, 326 {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"}, 327 {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"}, 328 {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"}, 329 {"GET", "images.google.com", "/search", 201, "/search"}, 330 {"GET", "images.google.com", "/search/", 404, ""}, 331 {"GET", "images.google.com", "/search/foo", 404, ""}, 332 {"GET", "google.com", "/../search", 301, "/search"}, 333 {"GET", "google.com", "/dir/..", 301, ""}, 334 {"GET", "google.com", "/dir/..", 301, ""}, 335 {"GET", "google.com", "/dir/./file", 301, "/dir/"}, 336 337 // The /foo -> /foo/ redirect applies to CONNECT requests 338 // but the path canonicalization does not. 339 {"CONNECT", "google.com", "/dir", 301, "/dir/"}, 340 {"CONNECT", "google.com", "/../search", 404, ""}, 341 {"CONNECT", "google.com", "/dir/..", 200, "/dir/"}, 342 {"CONNECT", "google.com", "/dir/..", 200, "/dir/"}, 343 {"CONNECT", "google.com", "/dir/./file", 200, "/dir/"}, 344 } 345 346 func TestServeMuxHandler(t *testing.T) { 347 mux := NewServeMux() 348 for _, e := range serveMuxRegister { 349 mux.Handle(e.pattern, e.h) 350 } 351 352 for _, tt := range serveMuxTests { 353 r := &Request{ 354 Method: tt.method, 355 Host: tt.host, 356 URL: &url.URL{ 357 Path: tt.path, 358 }, 359 } 360 h, pattern := mux.Handler(r) 361 rr := httptest.NewRecorder() 362 h.ServeHTTP(rr, r) 363 if pattern != tt.pattern || rr.Code != tt.code { 364 t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, rr.Code, pattern, tt.code, tt.pattern) 365 } 366 } 367 } 368 369 var serveMuxTests2 = []struct { 370 method string 371 host string 372 url string 373 code int 374 redirOk bool 375 }{ 376 {"GET", "google.com", "/", 404, false}, 377 {"GET", "example.com", "/test/?example.com/test/", 200, false}, 378 {"GET", "example.com", "test/?example.com/test/", 200, true}, 379 } 380 381 // TestServeMuxHandlerRedirects tests that automatic redirects generated by 382 // mux.Handler() shouldn't clear the request's query string. 383 func TestServeMuxHandlerRedirects(t *testing.T) { 384 mux := NewServeMux() 385 for _, e := range serveMuxRegister { 386 mux.Handle(e.pattern, e.h) 387 } 388 389 for _, tt := range serveMuxTests2 { 390 tries := 1 391 turl := tt.url 392 for tries > 0 { 393 u, e := url.Parse(turl) 394 if e != nil { 395 t.Fatal(e) 396 } 397 r := &Request{ 398 Method: tt.method, 399 Host: tt.host, 400 URL: u, 401 } 402 h, _ := mux.Handler(r) 403 rr := httptest.NewRecorder() 404 h.ServeHTTP(rr, r) 405 if rr.Code != 301 { 406 if rr.Code != tt.code { 407 t.Errorf("%s %s %s = %d, want %d", tt.method, tt.host, tt.url, rr.Code, tt.code) 408 } 409 break 410 } 411 if !tt.redirOk { 412 t.Errorf("%s %s %s, unexpected redirect", tt.method, tt.host, tt.url) 413 break 414 } 415 turl = rr.HeaderMap.Get("Location") 416 tries-- 417 } 418 if tries < 0 { 419 t.Errorf("%s %s %s, too many redirects", tt.method, tt.host, tt.url) 420 } 421 } 422 } 423 424 // Tests for https://golang.org/issue/900 425 func TestMuxRedirectLeadingSlashes(t *testing.T) { 426 paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"} 427 for _, path := range paths { 428 req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n"))) 429 if err != nil { 430 t.Errorf("%s", err) 431 } 432 mux := NewServeMux() 433 resp := httptest.NewRecorder() 434 435 mux.ServeHTTP(resp, req) 436 437 if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected { 438 t.Errorf("Expected Location header set to %q; got %q", expected, loc) 439 return 440 } 441 442 if code, expected := resp.Code, StatusMovedPermanently; code != expected { 443 t.Errorf("Expected response code of StatusMovedPermanently; got %d", code) 444 return 445 } 446 } 447 } 448 449 func TestServerTimeouts(t *testing.T) { 450 if runtime.GOOS == "plan9" { 451 t.Skip("skipping test; see https://golang.org/issue/7237") 452 } 453 defer afterTest(t) 454 reqNum := 0 455 ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) { 456 reqNum++ 457 fmt.Fprintf(res, "req=%d", reqNum) 458 })) 459 ts.Config.ReadTimeout = 250 * time.Millisecond 460 ts.Config.WriteTimeout = 250 * time.Millisecond 461 ts.Start() 462 defer ts.Close() 463 464 // Hit the HTTP server successfully. 465 tr := &Transport{DisableKeepAlives: true} // they interfere with this test 466 defer tr.CloseIdleConnections() 467 c := &Client{Transport: tr} 468 r, err := c.Get(ts.URL) 469 if err != nil { 470 t.Fatalf("http Get #1: %v", err) 471 } 472 got, _ := ioutil.ReadAll(r.Body) 473 expected := "req=1" 474 if string(got) != expected { 475 t.Errorf("Unexpected response for request #1; got %q; expected %q", 476 string(got), expected) 477 } 478 479 // Slow client that should timeout. 480 t1 := time.Now() 481 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 482 if err != nil { 483 t.Fatalf("Dial: %v", err) 484 } 485 buf := make([]byte, 1) 486 n, err := conn.Read(buf) 487 latency := time.Since(t1) 488 if n != 0 || err != io.EOF { 489 t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF) 490 } 491 if latency < 200*time.Millisecond /* fudge from 250 ms above */ { 492 t.Errorf("got EOF after %s, want >= %s", latency, 200*time.Millisecond) 493 } 494 495 // Hit the HTTP server successfully again, verifying that the 496 // previous slow connection didn't run our handler. (that we 497 // get "req=2", not "req=3") 498 r, err = Get(ts.URL) 499 if err != nil { 500 t.Fatalf("http Get #2: %v", err) 501 } 502 got, _ = ioutil.ReadAll(r.Body) 503 expected = "req=2" 504 if string(got) != expected { 505 t.Errorf("Get #2 got %q, want %q", string(got), expected) 506 } 507 508 if !testing.Short() { 509 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 510 if err != nil { 511 t.Fatalf("Dial: %v", err) 512 } 513 defer conn.Close() 514 go io.Copy(ioutil.Discard, conn) 515 for i := 0; i < 5; i++ { 516 _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")) 517 if err != nil { 518 t.Fatalf("on write %d: %v", i, err) 519 } 520 time.Sleep(ts.Config.ReadTimeout / 2) 521 } 522 } 523 } 524 525 // golang.org/issue/4741 -- setting only a write timeout that triggers 526 // shouldn't cause a handler to block forever on reads (next HTTP 527 // request) that will never happen. 528 func TestOnlyWriteTimeout(t *testing.T) { 529 if runtime.GOOS == "plan9" { 530 t.Skip("skipping test; see https://golang.org/issue/7237") 531 } 532 defer afterTest(t) 533 var conn net.Conn 534 var afterTimeoutErrc = make(chan error, 1) 535 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, req *Request) { 536 buf := make([]byte, 512<<10) 537 _, err := w.Write(buf) 538 if err != nil { 539 t.Errorf("handler Write error: %v", err) 540 return 541 } 542 conn.SetWriteDeadline(time.Now().Add(-30 * time.Second)) 543 _, err = w.Write(buf) 544 afterTimeoutErrc <- err 545 })) 546 ts.Listener = trackLastConnListener{ts.Listener, &conn} 547 ts.Start() 548 defer ts.Close() 549 550 tr := &Transport{DisableKeepAlives: false} 551 defer tr.CloseIdleConnections() 552 c := &Client{Transport: tr} 553 554 errc := make(chan error) 555 go func() { 556 res, err := c.Get(ts.URL) 557 if err != nil { 558 errc <- err 559 return 560 } 561 _, err = io.Copy(ioutil.Discard, res.Body) 562 errc <- err 563 }() 564 select { 565 case err := <-errc: 566 if err == nil { 567 t.Errorf("expected an error from Get request") 568 } 569 case <-time.After(5 * time.Second): 570 t.Fatal("timeout waiting for Get error") 571 } 572 if err := <-afterTimeoutErrc; err == nil { 573 t.Error("expected write error after timeout") 574 } 575 } 576 577 // trackLastConnListener tracks the last net.Conn that was accepted. 578 type trackLastConnListener struct { 579 net.Listener 580 last *net.Conn // destination 581 } 582 583 func (l trackLastConnListener) Accept() (c net.Conn, err error) { 584 c, err = l.Listener.Accept() 585 *l.last = c 586 return 587 } 588 589 // TestIdentityResponse verifies that a handler can unset 590 func TestIdentityResponse(t *testing.T) { 591 defer afterTest(t) 592 handler := HandlerFunc(func(rw ResponseWriter, req *Request) { 593 rw.Header().Set("Content-Length", "3") 594 rw.Header().Set("Transfer-Encoding", req.FormValue("te")) 595 switch { 596 case req.FormValue("overwrite") == "1": 597 _, err := rw.Write([]byte("foo TOO LONG")) 598 if err != ErrContentLength { 599 t.Errorf("expected ErrContentLength; got %v", err) 600 } 601 case req.FormValue("underwrite") == "1": 602 rw.Header().Set("Content-Length", "500") 603 rw.Write([]byte("too short")) 604 default: 605 rw.Write([]byte("foo")) 606 } 607 }) 608 609 ts := httptest.NewServer(handler) 610 defer ts.Close() 611 612 // Note: this relies on the assumption (which is true) that 613 // Get sends HTTP/1.1 or greater requests. Otherwise the 614 // server wouldn't have the choice to send back chunked 615 // responses. 616 for _, te := range []string{"", "identity"} { 617 url := ts.URL + "/?te=" + te 618 res, err := Get(url) 619 if err != nil { 620 t.Fatalf("error with Get of %s: %v", url, err) 621 } 622 if cl, expected := res.ContentLength, int64(3); cl != expected { 623 t.Errorf("for %s expected res.ContentLength of %d; got %d", url, expected, cl) 624 } 625 if cl, expected := res.Header.Get("Content-Length"), "3"; cl != expected { 626 t.Errorf("for %s expected Content-Length header of %q; got %q", url, expected, cl) 627 } 628 if tl, expected := len(res.TransferEncoding), 0; tl != expected { 629 t.Errorf("for %s expected len(res.TransferEncoding) of %d; got %d (%v)", 630 url, expected, tl, res.TransferEncoding) 631 } 632 res.Body.Close() 633 } 634 635 // Verify that ErrContentLength is returned 636 url := ts.URL + "/?overwrite=1" 637 res, err := Get(url) 638 if err != nil { 639 t.Fatalf("error with Get of %s: %v", url, err) 640 } 641 res.Body.Close() 642 643 // Verify that the connection is closed when the declared Content-Length 644 // is larger than what the handler wrote. 645 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 646 if err != nil { 647 t.Fatalf("error dialing: %v", err) 648 } 649 _, err = conn.Write([]byte("GET /?underwrite=1 HTTP/1.1\r\nHost: foo\r\n\r\n")) 650 if err != nil { 651 t.Fatalf("error writing: %v", err) 652 } 653 654 // The ReadAll will hang for a failing test, so use a Timer to 655 // fail explicitly. 656 goTimeout(t, 2*time.Second, func() { 657 got, _ := ioutil.ReadAll(conn) 658 expectedSuffix := "\r\n\r\ntoo short" 659 if !strings.HasSuffix(string(got), expectedSuffix) { 660 t.Errorf("Expected output to end with %q; got response body %q", 661 expectedSuffix, string(got)) 662 } 663 }) 664 } 665 666 func testTCPConnectionCloses(t *testing.T, req string, h Handler) { 667 defer afterTest(t) 668 s := httptest.NewServer(h) 669 defer s.Close() 670 671 conn, err := net.Dial("tcp", s.Listener.Addr().String()) 672 if err != nil { 673 t.Fatal("dial error:", err) 674 } 675 defer conn.Close() 676 677 _, err = fmt.Fprint(conn, req) 678 if err != nil { 679 t.Fatal("print error:", err) 680 } 681 682 r := bufio.NewReader(conn) 683 res, err := ReadResponse(r, &Request{Method: "GET"}) 684 if err != nil { 685 t.Fatal("ReadResponse error:", err) 686 } 687 688 didReadAll := make(chan bool, 1) 689 go func() { 690 select { 691 case <-time.After(5 * time.Second): 692 t.Error("body not closed after 5s") 693 return 694 case <-didReadAll: 695 } 696 }() 697 698 _, err = ioutil.ReadAll(r) 699 if err != nil { 700 t.Fatal("read error:", err) 701 } 702 didReadAll <- true 703 704 if !res.Close { 705 t.Errorf("Response.Close = false; want true") 706 } 707 } 708 709 // TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive. 710 func TestServeHTTP10Close(t *testing.T) { 711 testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) { 712 ServeFile(w, r, "testdata/file") 713 })) 714 } 715 716 // TestClientCanClose verifies that clients can also force a connection to close. 717 func TestClientCanClose(t *testing.T) { 718 testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) { 719 // Nothing. 720 })) 721 } 722 723 // TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close, 724 // even for HTTP/1.1 requests. 725 func TestHandlersCanSetConnectionClose11(t *testing.T) { 726 testTCPConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) { 727 w.Header().Set("Connection", "close") 728 })) 729 } 730 731 func TestHandlersCanSetConnectionClose10(t *testing.T) { 732 testTCPConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) { 733 w.Header().Set("Connection", "close") 734 })) 735 } 736 737 func TestSetsRemoteAddr(t *testing.T) { 738 defer afterTest(t) 739 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 740 fmt.Fprintf(w, "%s", r.RemoteAddr) 741 })) 742 defer ts.Close() 743 744 res, err := Get(ts.URL) 745 if err != nil { 746 t.Fatalf("Get error: %v", err) 747 } 748 body, err := ioutil.ReadAll(res.Body) 749 if err != nil { 750 t.Fatalf("ReadAll error: %v", err) 751 } 752 ip := string(body) 753 if !strings.HasPrefix(ip, "127.0.0.1:") && !strings.HasPrefix(ip, "[::1]:") { 754 t.Fatalf("Expected local addr; got %q", ip) 755 } 756 } 757 758 func TestChunkedResponseHeaders(t *testing.T) { 759 defer afterTest(t) 760 log.SetOutput(ioutil.Discard) // is noisy otherwise 761 defer log.SetOutput(os.Stderr) 762 763 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 764 w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted 765 w.(Flusher).Flush() 766 fmt.Fprintf(w, "I am a chunked response.") 767 })) 768 defer ts.Close() 769 770 res, err := Get(ts.URL) 771 if err != nil { 772 t.Fatalf("Get error: %v", err) 773 } 774 defer res.Body.Close() 775 if g, e := res.ContentLength, int64(-1); g != e { 776 t.Errorf("expected ContentLength of %d; got %d", e, g) 777 } 778 if g, e := res.TransferEncoding, []string{"chunked"}; !reflect.DeepEqual(g, e) { 779 t.Errorf("expected TransferEncoding of %v; got %v", e, g) 780 } 781 if _, haveCL := res.Header["Content-Length"]; haveCL { 782 t.Errorf("Unexpected Content-Length") 783 } 784 } 785 786 func TestIdentityResponseHeaders(t *testing.T) { 787 defer afterTest(t) 788 log.SetOutput(ioutil.Discard) // is noisy otherwise 789 defer log.SetOutput(os.Stderr) 790 791 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 792 w.Header().Set("Transfer-Encoding", "identity") 793 w.(Flusher).Flush() 794 fmt.Fprintf(w, "I am an identity response.") 795 })) 796 defer ts.Close() 797 798 res, err := Get(ts.URL) 799 if err != nil { 800 t.Fatalf("Get error: %v", err) 801 } 802 defer res.Body.Close() 803 804 if g, e := res.TransferEncoding, []string(nil); !reflect.DeepEqual(g, e) { 805 t.Errorf("expected TransferEncoding of %v; got %v", e, g) 806 } 807 if _, haveCL := res.Header["Content-Length"]; haveCL { 808 t.Errorf("Unexpected Content-Length") 809 } 810 if !res.Close { 811 t.Errorf("expected Connection: close; got %v", res.Close) 812 } 813 } 814 815 // Test304Responses verifies that 304s don't declare that they're 816 // chunking in their response headers and aren't allowed to produce 817 // output. 818 func Test304Responses(t *testing.T) { 819 defer afterTest(t) 820 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 821 w.WriteHeader(StatusNotModified) 822 _, err := w.Write([]byte("illegal body")) 823 if err != ErrBodyNotAllowed { 824 t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err) 825 } 826 })) 827 defer ts.Close() 828 res, err := Get(ts.URL) 829 if err != nil { 830 t.Error(err) 831 } 832 if len(res.TransferEncoding) > 0 { 833 t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding) 834 } 835 body, err := ioutil.ReadAll(res.Body) 836 if err != nil { 837 t.Error(err) 838 } 839 if len(body) > 0 { 840 t.Errorf("got unexpected body %q", string(body)) 841 } 842 } 843 844 // TestHeadResponses verifies that all MIME type sniffing and Content-Length 845 // counting of GET requests also happens on HEAD requests. 846 func TestHeadResponses(t *testing.T) { 847 defer afterTest(t) 848 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 849 _, err := w.Write([]byte("<html>")) 850 if err != nil { 851 t.Errorf("ResponseWriter.Write: %v", err) 852 } 853 854 // Also exercise the ReaderFrom path 855 _, err = io.Copy(w, strings.NewReader("789a")) 856 if err != nil { 857 t.Errorf("Copy(ResponseWriter, ...): %v", err) 858 } 859 })) 860 defer ts.Close() 861 res, err := Head(ts.URL) 862 if err != nil { 863 t.Error(err) 864 } 865 if len(res.TransferEncoding) > 0 { 866 t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding) 867 } 868 if ct := res.Header.Get("Content-Type"); ct != "text/html; charset=utf-8" { 869 t.Errorf("Content-Type: %q; want text/html; charset=utf-8", ct) 870 } 871 if v := res.ContentLength; v != 10 { 872 t.Errorf("Content-Length: %d; want 10", v) 873 } 874 body, err := ioutil.ReadAll(res.Body) 875 if err != nil { 876 t.Error(err) 877 } 878 if len(body) > 0 { 879 t.Errorf("got unexpected body %q", string(body)) 880 } 881 } 882 883 func TestTLSHandshakeTimeout(t *testing.T) { 884 if runtime.GOOS == "plan9" { 885 t.Skip("skipping test; see https://golang.org/issue/7237") 886 } 887 defer afterTest(t) 888 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 889 errc := make(chanWriter, 10) // but only expecting 1 890 ts.Config.ReadTimeout = 250 * time.Millisecond 891 ts.Config.ErrorLog = log.New(errc, "", 0) 892 ts.StartTLS() 893 defer ts.Close() 894 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 895 if err != nil { 896 t.Fatalf("Dial: %v", err) 897 } 898 defer conn.Close() 899 goTimeout(t, 10*time.Second, func() { 900 var buf [1]byte 901 n, err := conn.Read(buf[:]) 902 if err == nil || n != 0 { 903 t.Errorf("Read = %d, %v; want an error and no bytes", n, err) 904 } 905 }) 906 select { 907 case v := <-errc: 908 if !strings.Contains(v, "timeout") && !strings.Contains(v, "TLS handshake") { 909 t.Errorf("expected a TLS handshake timeout error; got %q", v) 910 } 911 case <-time.After(5 * time.Second): 912 t.Errorf("timeout waiting for logged error") 913 } 914 } 915 916 func TestTLSServer(t *testing.T) { 917 defer afterTest(t) 918 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 919 if r.TLS != nil { 920 w.Header().Set("X-TLS-Set", "true") 921 if r.TLS.HandshakeComplete { 922 w.Header().Set("X-TLS-HandshakeComplete", "true") 923 } 924 } 925 })) 926 ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0) 927 defer ts.Close() 928 929 // Connect an idle TCP connection to this server before we run 930 // our real tests. This idle connection used to block forever 931 // in the TLS handshake, preventing future connections from 932 // being accepted. It may prevent future accidental blocking 933 // in newConn. 934 idleConn, err := net.Dial("tcp", ts.Listener.Addr().String()) 935 if err != nil { 936 t.Fatalf("Dial: %v", err) 937 } 938 defer idleConn.Close() 939 goTimeout(t, 10*time.Second, func() { 940 if !strings.HasPrefix(ts.URL, "https://") { 941 t.Errorf("expected test TLS server to start with https://, got %q", ts.URL) 942 return 943 } 944 noVerifyTransport := &Transport{ 945 TLSClientConfig: &tls.Config{ 946 InsecureSkipVerify: true, 947 }, 948 } 949 client := &Client{Transport: noVerifyTransport} 950 res, err := client.Get(ts.URL) 951 if err != nil { 952 t.Error(err) 953 return 954 } 955 if res == nil { 956 t.Errorf("got nil Response") 957 return 958 } 959 defer res.Body.Close() 960 if res.Header.Get("X-TLS-Set") != "true" { 961 t.Errorf("expected X-TLS-Set response header") 962 return 963 } 964 if res.Header.Get("X-TLS-HandshakeComplete") != "true" { 965 t.Errorf("expected X-TLS-HandshakeComplete header") 966 } 967 }) 968 } 969 970 type serverExpectTest struct { 971 contentLength int // of request body 972 chunked bool 973 expectation string // e.g. "100-continue" 974 readBody bool // whether handler should read the body (if false, sends StatusUnauthorized) 975 expectedResponse string // expected substring in first line of http response 976 } 977 978 func expectTest(contentLength int, expectation string, readBody bool, expectedResponse string) serverExpectTest { 979 return serverExpectTest{ 980 contentLength: contentLength, 981 expectation: expectation, 982 readBody: readBody, 983 expectedResponse: expectedResponse, 984 } 985 } 986 987 var serverExpectTests = []serverExpectTest{ 988 // Normal 100-continues, case-insensitive. 989 expectTest(100, "100-continue", true, "100 Continue"), 990 expectTest(100, "100-cOntInUE", true, "100 Continue"), 991 992 // No 100-continue. 993 expectTest(100, "", true, "200 OK"), 994 995 // 100-continue but requesting client to deny us, 996 // so it never reads the body. 997 expectTest(100, "100-continue", false, "401 Unauthorized"), 998 // Likewise without 100-continue: 999 expectTest(100, "", false, "401 Unauthorized"), 1000 1001 // Non-standard expectations are failures 1002 expectTest(0, "a-pony", false, "417 Expectation Failed"), 1003 1004 // Expect-100 requested but no body (is apparently okay: Issue 7625) 1005 expectTest(0, "100-continue", true, "200 OK"), 1006 // Expect-100 requested but handler doesn't read the body 1007 expectTest(0, "100-continue", false, "401 Unauthorized"), 1008 // Expect-100 continue with no body, but a chunked body. 1009 { 1010 expectation: "100-continue", 1011 readBody: true, 1012 chunked: true, 1013 expectedResponse: "100 Continue", 1014 }, 1015 } 1016 1017 // Tests that the server responds to the "Expect" request header 1018 // correctly. 1019 func TestServerExpect(t *testing.T) { 1020 defer afterTest(t) 1021 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1022 // Note using r.FormValue("readbody") because for POST 1023 // requests that would read from r.Body, which we only 1024 // conditionally want to do. 1025 if strings.Contains(r.URL.RawQuery, "readbody=true") { 1026 ioutil.ReadAll(r.Body) 1027 w.Write([]byte("Hi")) 1028 } else { 1029 w.WriteHeader(StatusUnauthorized) 1030 } 1031 })) 1032 defer ts.Close() 1033 1034 runTest := func(test serverExpectTest) { 1035 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 1036 if err != nil { 1037 t.Fatalf("Dial: %v", err) 1038 } 1039 defer conn.Close() 1040 1041 // Only send the body immediately if we're acting like an HTTP client 1042 // that doesn't send 100-continue expectations. 1043 writeBody := test.contentLength != 0 && strings.ToLower(test.expectation) != "100-continue" 1044 1045 go func() { 1046 contentLen := fmt.Sprintf("Content-Length: %d", test.contentLength) 1047 if test.chunked { 1048 contentLen = "Transfer-Encoding: chunked" 1049 } 1050 _, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+ 1051 "Connection: close\r\n"+ 1052 "%s\r\n"+ 1053 "Expect: %s\r\nHost: foo\r\n\r\n", 1054 test.readBody, contentLen, test.expectation) 1055 if err != nil { 1056 t.Errorf("On test %#v, error writing request headers: %v", test, err) 1057 return 1058 } 1059 if writeBody { 1060 var targ io.WriteCloser = struct { 1061 io.Writer 1062 io.Closer 1063 }{ 1064 conn, 1065 ioutil.NopCloser(nil), 1066 } 1067 if test.chunked { 1068 targ = httputil.NewChunkedWriter(conn) 1069 } 1070 body := strings.Repeat("A", test.contentLength) 1071 _, err = fmt.Fprint(targ, body) 1072 if err == nil { 1073 err = targ.Close() 1074 } 1075 if err != nil { 1076 if !test.readBody { 1077 // Server likely already hung up on us. 1078 // See larger comment below. 1079 t.Logf("On test %#v, acceptable error writing request body: %v", test, err) 1080 return 1081 } 1082 t.Errorf("On test %#v, error writing request body: %v", test, err) 1083 } 1084 } 1085 }() 1086 bufr := bufio.NewReader(conn) 1087 line, err := bufr.ReadString('\n') 1088 if err != nil { 1089 if writeBody && !test.readBody { 1090 // This is an acceptable failure due to a possible TCP race: 1091 // We were still writing data and the server hung up on us. A TCP 1092 // implementation may send a RST if our request body data was known 1093 // to be lost, which may trigger our reads to fail. 1094 // See RFC 1122 page 88. 1095 t.Logf("On test %#v, acceptable error from ReadString: %v", test, err) 1096 return 1097 } 1098 t.Fatalf("On test %#v, ReadString: %v", test, err) 1099 } 1100 if !strings.Contains(line, test.expectedResponse) { 1101 t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse) 1102 } 1103 } 1104 1105 for _, test := range serverExpectTests { 1106 runTest(test) 1107 } 1108 } 1109 1110 // Under a ~256KB (maxPostHandlerReadBytes) threshold, the server 1111 // should consume client request bodies that a handler didn't read. 1112 func TestServerUnreadRequestBodyLittle(t *testing.T) { 1113 defer afterTest(t) 1114 conn := new(testConn) 1115 body := strings.Repeat("x", 100<<10) 1116 conn.readBuf.Write([]byte(fmt.Sprintf( 1117 "POST / HTTP/1.1\r\n"+ 1118 "Host: test\r\n"+ 1119 "Content-Length: %d\r\n"+ 1120 "\r\n", len(body)))) 1121 conn.readBuf.Write([]byte(body)) 1122 1123 done := make(chan bool) 1124 1125 ls := &oneConnListener{conn} 1126 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) { 1127 defer close(done) 1128 if conn.readBuf.Len() < len(body)/2 { 1129 t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len()) 1130 } 1131 rw.WriteHeader(200) 1132 rw.(Flusher).Flush() 1133 if g, e := conn.readBuf.Len(), 0; g != e { 1134 t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e) 1135 } 1136 if c := rw.Header().Get("Connection"); c != "" { 1137 t.Errorf(`Connection header = %q; want ""`, c) 1138 } 1139 })) 1140 <-done 1141 } 1142 1143 // Over a ~256KB (maxPostHandlerReadBytes) threshold, the server 1144 // should ignore client request bodies that a handler didn't read 1145 // and close the connection. 1146 func TestServerUnreadRequestBodyLarge(t *testing.T) { 1147 conn := new(testConn) 1148 body := strings.Repeat("x", 1<<20) 1149 conn.readBuf.Write([]byte(fmt.Sprintf( 1150 "POST / HTTP/1.1\r\n"+ 1151 "Host: test\r\n"+ 1152 "Content-Length: %d\r\n"+ 1153 "\r\n", len(body)))) 1154 conn.readBuf.Write([]byte(body)) 1155 conn.closec = make(chan bool, 1) 1156 1157 ls := &oneConnListener{conn} 1158 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) { 1159 if conn.readBuf.Len() < len(body)/2 { 1160 t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len()) 1161 } 1162 rw.WriteHeader(200) 1163 rw.(Flusher).Flush() 1164 if conn.readBuf.Len() < len(body)/2 { 1165 t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len()) 1166 } 1167 })) 1168 <-conn.closec 1169 1170 if res := conn.writeBuf.String(); !strings.Contains(res, "Connection: close") { 1171 t.Errorf("Expected a Connection: close header; got response: %s", res) 1172 } 1173 } 1174 1175 type handlerBodyCloseTest struct { 1176 bodySize int 1177 bodyChunked bool 1178 reqConnClose bool 1179 1180 wantEOFSearch bool // should Handler's Body.Close do Reads, looking for EOF? 1181 wantNextReq bool // should it find the next request on the same conn? 1182 } 1183 1184 func (t handlerBodyCloseTest) connectionHeader() string { 1185 if t.reqConnClose { 1186 return "Connection: close\r\n" 1187 } 1188 return "" 1189 } 1190 1191 var handlerBodyCloseTests = [...]handlerBodyCloseTest{ 1192 // Small enough to slurp past to the next request + 1193 // has Content-Length. 1194 0: { 1195 bodySize: 20 << 10, 1196 bodyChunked: false, 1197 reqConnClose: false, 1198 wantEOFSearch: true, 1199 wantNextReq: true, 1200 }, 1201 1202 // Small enough to slurp past to the next request + 1203 // is chunked. 1204 1: { 1205 bodySize: 20 << 10, 1206 bodyChunked: true, 1207 reqConnClose: false, 1208 wantEOFSearch: true, 1209 wantNextReq: true, 1210 }, 1211 1212 // Small enough to slurp past to the next request + 1213 // has Content-Length + 1214 // declares Connection: close (so pointless to read more). 1215 2: { 1216 bodySize: 20 << 10, 1217 bodyChunked: false, 1218 reqConnClose: true, 1219 wantEOFSearch: false, 1220 wantNextReq: false, 1221 }, 1222 1223 // Small enough to slurp past to the next request + 1224 // declares Connection: close, 1225 // but chunked, so it might have trailers. 1226 // TODO: maybe skip this search if no trailers were declared 1227 // in the headers. 1228 3: { 1229 bodySize: 20 << 10, 1230 bodyChunked: true, 1231 reqConnClose: true, 1232 wantEOFSearch: true, 1233 wantNextReq: false, 1234 }, 1235 1236 // Big with Content-Length, so give up immediately if we know it's too big. 1237 4: { 1238 bodySize: 1 << 20, 1239 bodyChunked: false, // has a Content-Length 1240 reqConnClose: false, 1241 wantEOFSearch: false, 1242 wantNextReq: false, 1243 }, 1244 1245 // Big chunked, so read a bit before giving up. 1246 5: { 1247 bodySize: 1 << 20, 1248 bodyChunked: true, 1249 reqConnClose: false, 1250 wantEOFSearch: true, 1251 wantNextReq: false, 1252 }, 1253 1254 // Big with Connection: close, but chunked, so search for trailers. 1255 // TODO: maybe skip this search if no trailers were declared 1256 // in the headers. 1257 6: { 1258 bodySize: 1 << 20, 1259 bodyChunked: true, 1260 reqConnClose: true, 1261 wantEOFSearch: true, 1262 wantNextReq: false, 1263 }, 1264 1265 // Big with Connection: close, so don't do any reads on Close. 1266 // With Content-Length. 1267 7: { 1268 bodySize: 1 << 20, 1269 bodyChunked: false, 1270 reqConnClose: true, 1271 wantEOFSearch: false, 1272 wantNextReq: false, 1273 }, 1274 } 1275 1276 func TestHandlerBodyClose(t *testing.T) { 1277 for i, tt := range handlerBodyCloseTests { 1278 testHandlerBodyClose(t, i, tt) 1279 } 1280 } 1281 1282 func testHandlerBodyClose(t *testing.T, i int, tt handlerBodyCloseTest) { 1283 conn := new(testConn) 1284 body := strings.Repeat("x", tt.bodySize) 1285 if tt.bodyChunked { 1286 conn.readBuf.WriteString("POST / HTTP/1.1\r\n" + 1287 "Host: test\r\n" + 1288 tt.connectionHeader() + 1289 "Transfer-Encoding: chunked\r\n" + 1290 "\r\n") 1291 cw := internal.NewChunkedWriter(&conn.readBuf) 1292 io.WriteString(cw, body) 1293 cw.Close() 1294 conn.readBuf.WriteString("\r\n") 1295 } else { 1296 conn.readBuf.Write([]byte(fmt.Sprintf( 1297 "POST / HTTP/1.1\r\n"+ 1298 "Host: test\r\n"+ 1299 tt.connectionHeader()+ 1300 "Content-Length: %d\r\n"+ 1301 "\r\n", len(body)))) 1302 conn.readBuf.Write([]byte(body)) 1303 } 1304 if !tt.reqConnClose { 1305 conn.readBuf.WriteString("GET / HTTP/1.1\r\nHost: test\r\n\r\n") 1306 } 1307 conn.closec = make(chan bool, 1) 1308 1309 ls := &oneConnListener{conn} 1310 var numReqs int 1311 var size0, size1 int 1312 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) { 1313 numReqs++ 1314 if numReqs == 1 { 1315 size0 = conn.readBuf.Len() 1316 req.Body.Close() 1317 size1 = conn.readBuf.Len() 1318 } 1319 })) 1320 <-conn.closec 1321 if numReqs < 1 || numReqs > 2 { 1322 t.Fatalf("%d. bug in test. unexpected number of requests = %d", i, numReqs) 1323 } 1324 didSearch := size0 != size1 1325 if didSearch != tt.wantEOFSearch { 1326 t.Errorf("%d. did EOF search = %v; want %v (size went from %d to %d)", i, didSearch, !didSearch, size0, size1) 1327 } 1328 if tt.wantNextReq && numReqs != 2 { 1329 t.Errorf("%d. numReq = %d; want 2", i, numReqs) 1330 } 1331 } 1332 1333 // testHandlerBodyConsumer represents a function injected into a test handler to 1334 // vary work done on a request Body. 1335 type testHandlerBodyConsumer struct { 1336 name string 1337 f func(io.ReadCloser) 1338 } 1339 1340 var testHandlerBodyConsumers = []testHandlerBodyConsumer{ 1341 {"nil", func(io.ReadCloser) {}}, 1342 {"close", func(r io.ReadCloser) { r.Close() }}, 1343 {"discard", func(r io.ReadCloser) { io.Copy(ioutil.Discard, r) }}, 1344 } 1345 1346 func TestRequestBodyReadErrorClosesConnection(t *testing.T) { 1347 defer afterTest(t) 1348 for _, handler := range testHandlerBodyConsumers { 1349 conn := new(testConn) 1350 conn.readBuf.WriteString("POST /public HTTP/1.1\r\n" + 1351 "Host: test\r\n" + 1352 "Transfer-Encoding: chunked\r\n" + 1353 "\r\n" + 1354 "hax\r\n" + // Invalid chunked encoding 1355 "GET /secret HTTP/1.1\r\n" + 1356 "Host: test\r\n" + 1357 "\r\n") 1358 1359 conn.closec = make(chan bool, 1) 1360 ls := &oneConnListener{conn} 1361 var numReqs int 1362 go Serve(ls, HandlerFunc(func(_ ResponseWriter, req *Request) { 1363 numReqs++ 1364 if strings.Contains(req.URL.Path, "secret") { 1365 t.Error("Request for /secret encountered, should not have happened.") 1366 } 1367 handler.f(req.Body) 1368 })) 1369 <-conn.closec 1370 if numReqs != 1 { 1371 t.Errorf("Handler %v: got %d reqs; want 1", handler.name, numReqs) 1372 } 1373 } 1374 } 1375 1376 func TestInvalidTrailerClosesConnection(t *testing.T) { 1377 defer afterTest(t) 1378 for _, handler := range testHandlerBodyConsumers { 1379 conn := new(testConn) 1380 conn.readBuf.WriteString("POST /public HTTP/1.1\r\n" + 1381 "Host: test\r\n" + 1382 "Trailer: hack\r\n" + 1383 "Transfer-Encoding: chunked\r\n" + 1384 "\r\n" + 1385 "3\r\n" + 1386 "hax\r\n" + 1387 "0\r\n" + 1388 "I'm not a valid trailer\r\n" + 1389 "GET /secret HTTP/1.1\r\n" + 1390 "Host: test\r\n" + 1391 "\r\n") 1392 1393 conn.closec = make(chan bool, 1) 1394 ln := &oneConnListener{conn} 1395 var numReqs int 1396 go Serve(ln, HandlerFunc(func(_ ResponseWriter, req *Request) { 1397 numReqs++ 1398 if strings.Contains(req.URL.Path, "secret") { 1399 t.Errorf("Handler %s, Request for /secret encountered, should not have happened.", handler.name) 1400 } 1401 handler.f(req.Body) 1402 })) 1403 <-conn.closec 1404 if numReqs != 1 { 1405 t.Errorf("Handler %s: got %d reqs; want 1", handler.name, numReqs) 1406 } 1407 } 1408 } 1409 1410 // slowTestConn is a net.Conn that provides a means to simulate parts of a 1411 // request being received piecemeal. Deadlines can be set and enforced in both 1412 // Read and Write. 1413 type slowTestConn struct { 1414 // over multiple calls to Read, time.Durations are slept, strings are read. 1415 script []interface{} 1416 closec chan bool 1417 rd, wd time.Time // read, write deadline 1418 noopConn 1419 } 1420 1421 func (c *slowTestConn) SetDeadline(t time.Time) error { 1422 c.SetReadDeadline(t) 1423 c.SetWriteDeadline(t) 1424 return nil 1425 } 1426 1427 func (c *slowTestConn) SetReadDeadline(t time.Time) error { 1428 c.rd = t 1429 return nil 1430 } 1431 1432 func (c *slowTestConn) SetWriteDeadline(t time.Time) error { 1433 c.wd = t 1434 return nil 1435 } 1436 1437 func (c *slowTestConn) Read(b []byte) (n int, err error) { 1438 restart: 1439 if !c.rd.IsZero() && time.Now().After(c.rd) { 1440 return 0, syscall.ETIMEDOUT 1441 } 1442 if len(c.script) == 0 { 1443 return 0, io.EOF 1444 } 1445 1446 switch cue := c.script[0].(type) { 1447 case time.Duration: 1448 if !c.rd.IsZero() { 1449 // If the deadline falls in the middle of our sleep window, deduct 1450 // part of the sleep, then return a timeout. 1451 if remaining := c.rd.Sub(time.Now()); remaining < cue { 1452 c.script[0] = cue - remaining 1453 time.Sleep(remaining) 1454 return 0, syscall.ETIMEDOUT 1455 } 1456 } 1457 c.script = c.script[1:] 1458 time.Sleep(cue) 1459 goto restart 1460 1461 case string: 1462 n = copy(b, cue) 1463 // If cue is too big for the buffer, leave the end for the next Read. 1464 if len(cue) > n { 1465 c.script[0] = cue[n:] 1466 } else { 1467 c.script = c.script[1:] 1468 } 1469 1470 default: 1471 panic("unknown cue in slowTestConn script") 1472 } 1473 1474 return 1475 } 1476 1477 func (c *slowTestConn) Close() error { 1478 select { 1479 case c.closec <- true: 1480 default: 1481 } 1482 return nil 1483 } 1484 1485 func (c *slowTestConn) Write(b []byte) (int, error) { 1486 if !c.wd.IsZero() && time.Now().After(c.wd) { 1487 return 0, syscall.ETIMEDOUT 1488 } 1489 return len(b), nil 1490 } 1491 1492 func TestRequestBodyTimeoutClosesConnection(t *testing.T) { 1493 if testing.Short() { 1494 t.Skip("skipping in -short mode") 1495 } 1496 defer afterTest(t) 1497 for _, handler := range testHandlerBodyConsumers { 1498 conn := &slowTestConn{ 1499 script: []interface{}{ 1500 "POST /public HTTP/1.1\r\n" + 1501 "Host: test\r\n" + 1502 "Content-Length: 10000\r\n" + 1503 "\r\n", 1504 "foo bar baz", 1505 600 * time.Millisecond, // Request deadline should hit here 1506 "GET /secret HTTP/1.1\r\n" + 1507 "Host: test\r\n" + 1508 "\r\n", 1509 }, 1510 closec: make(chan bool, 1), 1511 } 1512 ls := &oneConnListener{conn} 1513 1514 var numReqs int 1515 s := Server{ 1516 Handler: HandlerFunc(func(_ ResponseWriter, req *Request) { 1517 numReqs++ 1518 if strings.Contains(req.URL.Path, "secret") { 1519 t.Error("Request for /secret encountered, should not have happened.") 1520 } 1521 handler.f(req.Body) 1522 }), 1523 ReadTimeout: 400 * time.Millisecond, 1524 } 1525 go s.Serve(ls) 1526 <-conn.closec 1527 1528 if numReqs != 1 { 1529 t.Errorf("Handler %v: got %d reqs; want 1", handler.name, numReqs) 1530 } 1531 } 1532 } 1533 1534 func TestTimeoutHandler(t *testing.T) { 1535 defer afterTest(t) 1536 sendHi := make(chan bool, 1) 1537 writeErrors := make(chan error, 1) 1538 sayHi := HandlerFunc(func(w ResponseWriter, r *Request) { 1539 <-sendHi 1540 _, werr := w.Write([]byte("hi")) 1541 writeErrors <- werr 1542 }) 1543 timeout := make(chan time.Time, 1) // write to this to force timeouts 1544 ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout)) 1545 defer ts.Close() 1546 1547 // Succeed without timing out: 1548 sendHi <- true 1549 res, err := Get(ts.URL) 1550 if err != nil { 1551 t.Error(err) 1552 } 1553 if g, e := res.StatusCode, StatusOK; g != e { 1554 t.Errorf("got res.StatusCode %d; expected %d", g, e) 1555 } 1556 body, _ := ioutil.ReadAll(res.Body) 1557 if g, e := string(body), "hi"; g != e { 1558 t.Errorf("got body %q; expected %q", g, e) 1559 } 1560 if g := <-writeErrors; g != nil { 1561 t.Errorf("got unexpected Write error on first request: %v", g) 1562 } 1563 1564 // Times out: 1565 timeout <- time.Time{} 1566 res, err = Get(ts.URL) 1567 if err != nil { 1568 t.Error(err) 1569 } 1570 if g, e := res.StatusCode, StatusServiceUnavailable; g != e { 1571 t.Errorf("got res.StatusCode %d; expected %d", g, e) 1572 } 1573 body, _ = ioutil.ReadAll(res.Body) 1574 if !strings.Contains(string(body), "<title>Timeout</title>") { 1575 t.Errorf("expected timeout body; got %q", string(body)) 1576 } 1577 1578 // Now make the previously-timed out handler speak again, 1579 // which verifies the panic is handled: 1580 sendHi <- true 1581 if g, e := <-writeErrors, ErrHandlerTimeout; g != e { 1582 t.Errorf("expected Write error of %v; got %v", e, g) 1583 } 1584 } 1585 1586 // See issues 8209 and 8414. 1587 func TestTimeoutHandlerRace(t *testing.T) { 1588 defer afterTest(t) 1589 1590 delayHi := HandlerFunc(func(w ResponseWriter, r *Request) { 1591 ms, _ := strconv.Atoi(r.URL.Path[1:]) 1592 if ms == 0 { 1593 ms = 1 1594 } 1595 for i := 0; i < ms; i++ { 1596 w.Write([]byte("hi")) 1597 time.Sleep(time.Millisecond) 1598 } 1599 }) 1600 1601 ts := httptest.NewServer(TimeoutHandler(delayHi, 20*time.Millisecond, "")) 1602 defer ts.Close() 1603 1604 var wg sync.WaitGroup 1605 gate := make(chan bool, 10) 1606 n := 50 1607 if testing.Short() { 1608 n = 10 1609 gate = make(chan bool, 3) 1610 } 1611 for i := 0; i < n; i++ { 1612 gate <- true 1613 wg.Add(1) 1614 go func() { 1615 defer wg.Done() 1616 defer func() { <-gate }() 1617 res, err := Get(fmt.Sprintf("%s/%d", ts.URL, rand.Intn(50))) 1618 if err == nil { 1619 io.Copy(ioutil.Discard, res.Body) 1620 res.Body.Close() 1621 } 1622 }() 1623 } 1624 wg.Wait() 1625 } 1626 1627 // See issues 8209 and 8414. 1628 func TestTimeoutHandlerRaceHeader(t *testing.T) { 1629 defer afterTest(t) 1630 1631 delay204 := HandlerFunc(func(w ResponseWriter, r *Request) { 1632 w.WriteHeader(204) 1633 }) 1634 1635 ts := httptest.NewServer(TimeoutHandler(delay204, time.Nanosecond, "")) 1636 defer ts.Close() 1637 1638 var wg sync.WaitGroup 1639 gate := make(chan bool, 50) 1640 n := 500 1641 if testing.Short() { 1642 n = 10 1643 } 1644 for i := 0; i < n; i++ { 1645 gate <- true 1646 wg.Add(1) 1647 go func() { 1648 defer wg.Done() 1649 defer func() { <-gate }() 1650 res, err := Get(ts.URL) 1651 if err != nil { 1652 t.Error(err) 1653 return 1654 } 1655 defer res.Body.Close() 1656 io.Copy(ioutil.Discard, res.Body) 1657 }() 1658 } 1659 wg.Wait() 1660 } 1661 1662 // Verifies we don't path.Clean() on the wrong parts in redirects. 1663 func TestRedirectMunging(t *testing.T) { 1664 req, _ := NewRequest("GET", "http://example.com/", nil) 1665 1666 resp := httptest.NewRecorder() 1667 Redirect(resp, req, "/foo?next=http://bar.com/", 302) 1668 if g, e := resp.Header().Get("Location"), "/foo?next=http://bar.com/"; g != e { 1669 t.Errorf("Location header was %q; want %q", g, e) 1670 } 1671 1672 resp = httptest.NewRecorder() 1673 Redirect(resp, req, "http://localhost:8080/_ah/login?continue=http://localhost:8080/", 302) 1674 if g, e := resp.Header().Get("Location"), "http://localhost:8080/_ah/login?continue=http://localhost:8080/"; g != e { 1675 t.Errorf("Location header was %q; want %q", g, e) 1676 } 1677 } 1678 1679 func TestRedirectBadPath(t *testing.T) { 1680 // This used to crash. It's not valid input (bad path), but it 1681 // shouldn't crash. 1682 rr := httptest.NewRecorder() 1683 req := &Request{ 1684 Method: "GET", 1685 URL: &url.URL{ 1686 Scheme: "http", 1687 Path: "not-empty-but-no-leading-slash", // bogus 1688 }, 1689 } 1690 Redirect(rr, req, "", 304) 1691 if rr.Code != 304 { 1692 t.Errorf("Code = %d; want 304", rr.Code) 1693 } 1694 } 1695 1696 // TestZeroLengthPostAndResponse exercises an optimization done by the Transport: 1697 // when there is no body (either because the method doesn't permit a body, or an 1698 // explicit Content-Length of zero is present), then the transport can re-use the 1699 // connection immediately. But when it re-uses the connection, it typically closes 1700 // the previous request's body, which is not optimal for zero-lengthed bodies, 1701 // as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF. 1702 func TestZeroLengthPostAndResponse(t *testing.T) { 1703 defer afterTest(t) 1704 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) { 1705 all, err := ioutil.ReadAll(r.Body) 1706 if err != nil { 1707 t.Fatalf("handler ReadAll: %v", err) 1708 } 1709 if len(all) != 0 { 1710 t.Errorf("handler got %d bytes; expected 0", len(all)) 1711 } 1712 rw.Header().Set("Content-Length", "0") 1713 })) 1714 defer ts.Close() 1715 1716 req, err := NewRequest("POST", ts.URL, strings.NewReader("")) 1717 if err != nil { 1718 t.Fatal(err) 1719 } 1720 req.ContentLength = 0 1721 1722 var resp [5]*Response 1723 for i := range resp { 1724 resp[i], err = DefaultClient.Do(req) 1725 if err != nil { 1726 t.Fatalf("client post #%d: %v", i, err) 1727 } 1728 } 1729 1730 for i := range resp { 1731 all, err := ioutil.ReadAll(resp[i].Body) 1732 if err != nil { 1733 t.Fatalf("req #%d: client ReadAll: %v", i, err) 1734 } 1735 if len(all) != 0 { 1736 t.Errorf("req #%d: client got %d bytes; expected 0", i, len(all)) 1737 } 1738 } 1739 } 1740 1741 func TestHandlerPanicNil(t *testing.T) { 1742 testHandlerPanic(t, false, nil) 1743 } 1744 1745 func TestHandlerPanic(t *testing.T) { 1746 testHandlerPanic(t, false, "intentional death for testing") 1747 } 1748 1749 func TestHandlerPanicWithHijack(t *testing.T) { 1750 testHandlerPanic(t, true, "intentional death for testing") 1751 } 1752 1753 func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) { 1754 defer afterTest(t) 1755 // Unlike the other tests that set the log output to ioutil.Discard 1756 // to quiet the output, this test uses a pipe. The pipe serves three 1757 // purposes: 1758 // 1759 // 1) The log.Print from the http server (generated by the caught 1760 // panic) will go to the pipe instead of stderr, making the 1761 // output quiet. 1762 // 1763 // 2) We read from the pipe to verify that the handler 1764 // actually caught the panic and logged something. 1765 // 1766 // 3) The blocking Read call prevents this TestHandlerPanic 1767 // function from exiting before the HTTP server handler 1768 // finishes crashing. If this text function exited too 1769 // early (and its defer log.SetOutput(os.Stderr) ran), 1770 // then the crash output could spill into the next test. 1771 pr, pw := io.Pipe() 1772 log.SetOutput(pw) 1773 defer log.SetOutput(os.Stderr) 1774 defer pw.Close() 1775 1776 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1777 if withHijack { 1778 rwc, _, err := w.(Hijacker).Hijack() 1779 if err != nil { 1780 t.Logf("unexpected error: %v", err) 1781 } 1782 defer rwc.Close() 1783 } 1784 panic(panicValue) 1785 })) 1786 defer ts.Close() 1787 1788 // Do a blocking read on the log output pipe so its logging 1789 // doesn't bleed into the next test. But wait only 5 seconds 1790 // for it. 1791 done := make(chan bool, 1) 1792 go func() { 1793 buf := make([]byte, 4<<10) 1794 _, err := pr.Read(buf) 1795 pr.Close() 1796 if err != nil && err != io.EOF { 1797 t.Error(err) 1798 } 1799 done <- true 1800 }() 1801 1802 _, err := Get(ts.URL) 1803 if err == nil { 1804 t.Logf("expected an error") 1805 } 1806 1807 if panicValue == nil { 1808 return 1809 } 1810 1811 select { 1812 case <-done: 1813 return 1814 case <-time.After(5 * time.Second): 1815 t.Fatal("expected server handler to log an error") 1816 } 1817 } 1818 1819 func TestServerNoDate(t *testing.T) { testServerNoHeader(t, "Date") } 1820 func TestServerNoContentType(t *testing.T) { testServerNoHeader(t, "Content-Type") } 1821 1822 func testServerNoHeader(t *testing.T, header string) { 1823 defer afterTest(t) 1824 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1825 w.Header()[header] = nil 1826 io.WriteString(w, "<html>foo</html>") // non-empty 1827 })) 1828 defer ts.Close() 1829 res, err := Get(ts.URL) 1830 if err != nil { 1831 t.Fatal(err) 1832 } 1833 res.Body.Close() 1834 if got, ok := res.Header[header]; ok { 1835 t.Fatalf("Expected no %s header; got %q", header, got) 1836 } 1837 } 1838 1839 func TestStripPrefix(t *testing.T) { 1840 defer afterTest(t) 1841 h := HandlerFunc(func(w ResponseWriter, r *Request) { 1842 w.Header().Set("X-Path", r.URL.Path) 1843 }) 1844 ts := httptest.NewServer(StripPrefix("/foo", h)) 1845 defer ts.Close() 1846 1847 res, err := Get(ts.URL + "/foo/bar") 1848 if err != nil { 1849 t.Fatal(err) 1850 } 1851 if g, e := res.Header.Get("X-Path"), "/bar"; g != e { 1852 t.Errorf("test 1: got %s, want %s", g, e) 1853 } 1854 res.Body.Close() 1855 1856 res, err = Get(ts.URL + "/bar") 1857 if err != nil { 1858 t.Fatal(err) 1859 } 1860 if g, e := res.StatusCode, 404; g != e { 1861 t.Errorf("test 2: got status %v, want %v", g, e) 1862 } 1863 res.Body.Close() 1864 } 1865 1866 func TestRequestLimit(t *testing.T) { 1867 defer afterTest(t) 1868 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1869 t.Fatalf("didn't expect to get request in Handler") 1870 })) 1871 defer ts.Close() 1872 req, _ := NewRequest("GET", ts.URL, nil) 1873 var bytesPerHeader = len("header12345: val12345\r\n") 1874 for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ { 1875 req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i)) 1876 } 1877 res, err := DefaultClient.Do(req) 1878 if err != nil { 1879 // Some HTTP clients may fail on this undefined behavior (server replying and 1880 // closing the connection while the request is still being written), but 1881 // we do support it (at least currently), so we expect a response below. 1882 t.Fatalf("Do: %v", err) 1883 } 1884 defer res.Body.Close() 1885 if res.StatusCode != 413 { 1886 t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status) 1887 } 1888 } 1889 1890 type neverEnding byte 1891 1892 func (b neverEnding) Read(p []byte) (n int, err error) { 1893 for i := range p { 1894 p[i] = byte(b) 1895 } 1896 return len(p), nil 1897 } 1898 1899 type countReader struct { 1900 r io.Reader 1901 n *int64 1902 } 1903 1904 func (cr countReader) Read(p []byte) (n int, err error) { 1905 n, err = cr.r.Read(p) 1906 atomic.AddInt64(cr.n, int64(n)) 1907 return 1908 } 1909 1910 func TestRequestBodyLimit(t *testing.T) { 1911 defer afterTest(t) 1912 const limit = 1 << 20 1913 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1914 r.Body = MaxBytesReader(w, r.Body, limit) 1915 n, err := io.Copy(ioutil.Discard, r.Body) 1916 if err == nil { 1917 t.Errorf("expected error from io.Copy") 1918 } 1919 if n != limit { 1920 t.Errorf("io.Copy = %d, want %d", n, limit) 1921 } 1922 })) 1923 defer ts.Close() 1924 1925 nWritten := new(int64) 1926 req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200)) 1927 1928 // Send the POST, but don't care it succeeds or not. The 1929 // remote side is going to reply and then close the TCP 1930 // connection, and HTTP doesn't really define if that's 1931 // allowed or not. Some HTTP clients will get the response 1932 // and some (like ours, currently) will complain that the 1933 // request write failed, without reading the response. 1934 // 1935 // But that's okay, since what we're really testing is that 1936 // the remote side hung up on us before we wrote too much. 1937 _, _ = DefaultClient.Do(req) 1938 1939 if atomic.LoadInt64(nWritten) > limit*100 { 1940 t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d", 1941 limit, nWritten) 1942 } 1943 } 1944 1945 // TestClientWriteShutdown tests that if the client shuts down the write 1946 // side of their TCP connection, the server doesn't send a 400 Bad Request. 1947 func TestClientWriteShutdown(t *testing.T) { 1948 if runtime.GOOS == "plan9" { 1949 t.Skip("skipping test; see https://golang.org/issue/7237") 1950 } 1951 defer afterTest(t) 1952 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 1953 defer ts.Close() 1954 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 1955 if err != nil { 1956 t.Fatalf("Dial: %v", err) 1957 } 1958 err = conn.(*net.TCPConn).CloseWrite() 1959 if err != nil { 1960 t.Fatalf("Dial: %v", err) 1961 } 1962 donec := make(chan bool) 1963 go func() { 1964 defer close(donec) 1965 bs, err := ioutil.ReadAll(conn) 1966 if err != nil { 1967 t.Fatalf("ReadAll: %v", err) 1968 } 1969 got := string(bs) 1970 if got != "" { 1971 t.Errorf("read %q from server; want nothing", got) 1972 } 1973 }() 1974 select { 1975 case <-donec: 1976 case <-time.After(10 * time.Second): 1977 t.Fatalf("timeout") 1978 } 1979 } 1980 1981 // Tests that chunked server responses that write 1 byte at a time are 1982 // buffered before chunk headers are added, not after chunk headers. 1983 func TestServerBufferedChunking(t *testing.T) { 1984 conn := new(testConn) 1985 conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n")) 1986 conn.closec = make(chan bool, 1) 1987 ls := &oneConnListener{conn} 1988 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) { 1989 rw.(Flusher).Flush() // force the Header to be sent, in chunking mode, not counting the length 1990 rw.Write([]byte{'x'}) 1991 rw.Write([]byte{'y'}) 1992 rw.Write([]byte{'z'}) 1993 })) 1994 <-conn.closec 1995 if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) { 1996 t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q", 1997 conn.writeBuf.Bytes()) 1998 } 1999 } 2000 2001 // Tests that the server flushes its response headers out when it's 2002 // ignoring the response body and waits a bit before forcefully 2003 // closing the TCP connection, causing the client to get a RST. 2004 // See https://golang.org/issue/3595 2005 func TestServerGracefulClose(t *testing.T) { 2006 defer afterTest(t) 2007 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2008 Error(w, "bye", StatusUnauthorized) 2009 })) 2010 defer ts.Close() 2011 2012 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 2013 if err != nil { 2014 t.Fatal(err) 2015 } 2016 defer conn.Close() 2017 const bodySize = 5 << 20 2018 req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize)) 2019 for i := 0; i < bodySize; i++ { 2020 req = append(req, 'x') 2021 } 2022 writeErr := make(chan error) 2023 go func() { 2024 _, err := conn.Write(req) 2025 writeErr <- err 2026 }() 2027 br := bufio.NewReader(conn) 2028 lineNum := 0 2029 for { 2030 line, err := br.ReadString('\n') 2031 if err == io.EOF { 2032 break 2033 } 2034 if err != nil { 2035 t.Fatalf("ReadLine: %v", err) 2036 } 2037 lineNum++ 2038 if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") { 2039 t.Errorf("Response line = %q; want a 401", line) 2040 } 2041 } 2042 // Wait for write to finish. This is a broken pipe on both 2043 // Darwin and Linux, but checking this isn't the point of 2044 // the test. 2045 <-writeErr 2046 } 2047 2048 func TestCaseSensitiveMethod(t *testing.T) { 2049 defer afterTest(t) 2050 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2051 if r.Method != "get" { 2052 t.Errorf(`Got method %q; want "get"`, r.Method) 2053 } 2054 })) 2055 defer ts.Close() 2056 req, _ := NewRequest("get", ts.URL, nil) 2057 res, err := DefaultClient.Do(req) 2058 if err != nil { 2059 t.Error(err) 2060 return 2061 } 2062 res.Body.Close() 2063 } 2064 2065 // TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1 2066 // request (both keep-alive), when a Handler never writes any 2067 // response, the net/http package adds a "Content-Length: 0" response 2068 // header. 2069 func TestContentLengthZero(t *testing.T) { 2070 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {})) 2071 defer ts.Close() 2072 2073 for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} { 2074 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 2075 if err != nil { 2076 t.Fatalf("error dialing: %v", err) 2077 } 2078 _, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version) 2079 if err != nil { 2080 t.Fatalf("error writing: %v", err) 2081 } 2082 req, _ := NewRequest("GET", "/", nil) 2083 res, err := ReadResponse(bufio.NewReader(conn), req) 2084 if err != nil { 2085 t.Fatalf("error reading response: %v", err) 2086 } 2087 if te := res.TransferEncoding; len(te) > 0 { 2088 t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te) 2089 } 2090 if cl := res.ContentLength; cl != 0 { 2091 t.Errorf("For version %q, Content-Length = %v; want 0", version, cl) 2092 } 2093 conn.Close() 2094 } 2095 } 2096 2097 func TestCloseNotifier(t *testing.T) { 2098 defer afterTest(t) 2099 gotReq := make(chan bool, 1) 2100 sawClose := make(chan bool, 1) 2101 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 2102 gotReq <- true 2103 cc := rw.(CloseNotifier).CloseNotify() 2104 <-cc 2105 sawClose <- true 2106 })) 2107 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 2108 if err != nil { 2109 t.Fatalf("error dialing: %v", err) 2110 } 2111 diec := make(chan bool) 2112 go func() { 2113 _, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n") 2114 if err != nil { 2115 t.Fatal(err) 2116 } 2117 <-diec 2118 conn.Close() 2119 }() 2120 For: 2121 for { 2122 select { 2123 case <-gotReq: 2124 diec <- true 2125 case <-sawClose: 2126 break For 2127 case <-time.After(5 * time.Second): 2128 t.Fatal("timeout") 2129 } 2130 } 2131 ts.Close() 2132 } 2133 2134 func TestCloseNotifierChanLeak(t *testing.T) { 2135 defer afterTest(t) 2136 req := reqBytes("GET / HTTP/1.0\nHost: golang.org") 2137 for i := 0; i < 20; i++ { 2138 var output bytes.Buffer 2139 conn := &rwTestConn{ 2140 Reader: bytes.NewReader(req), 2141 Writer: &output, 2142 closec: make(chan bool, 1), 2143 } 2144 ln := &oneConnListener{conn: conn} 2145 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 2146 // Ignore the return value and never read from 2147 // it, testing that we don't leak goroutines 2148 // on the sending side: 2149 _ = rw.(CloseNotifier).CloseNotify() 2150 }) 2151 go Serve(ln, handler) 2152 <-conn.closec 2153 } 2154 } 2155 2156 func TestOptions(t *testing.T) { 2157 uric := make(chan string, 2) // only expect 1, but leave space for 2 2158 mux := NewServeMux() 2159 mux.HandleFunc("/", func(w ResponseWriter, r *Request) { 2160 uric <- r.RequestURI 2161 }) 2162 ts := httptest.NewServer(mux) 2163 defer ts.Close() 2164 2165 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 2166 if err != nil { 2167 t.Fatal(err) 2168 } 2169 defer conn.Close() 2170 2171 // An OPTIONS * request should succeed. 2172 _, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n")) 2173 if err != nil { 2174 t.Fatal(err) 2175 } 2176 br := bufio.NewReader(conn) 2177 res, err := ReadResponse(br, &Request{Method: "OPTIONS"}) 2178 if err != nil { 2179 t.Fatal(err) 2180 } 2181 if res.StatusCode != 200 { 2182 t.Errorf("Got non-200 response to OPTIONS *: %#v", res) 2183 } 2184 2185 // A GET * request on a ServeMux should fail. 2186 _, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n")) 2187 if err != nil { 2188 t.Fatal(err) 2189 } 2190 res, err = ReadResponse(br, &Request{Method: "GET"}) 2191 if err != nil { 2192 t.Fatal(err) 2193 } 2194 if res.StatusCode != 400 { 2195 t.Errorf("Got non-400 response to GET *: %#v", res) 2196 } 2197 2198 res, err = Get(ts.URL + "/second") 2199 if err != nil { 2200 t.Fatal(err) 2201 } 2202 res.Body.Close() 2203 if got := <-uric; got != "/second" { 2204 t.Errorf("Handler saw request for %q; want /second", got) 2205 } 2206 } 2207 2208 // Tests regarding the ordering of Write, WriteHeader, Header, and 2209 // Flush calls. In Go 1.0, rw.WriteHeader immediately flushed the 2210 // (*response).header to the wire. In Go 1.1, the actual wire flush is 2211 // delayed, so we could maybe tack on a Content-Length and better 2212 // Content-Type after we see more (or all) of the output. To preserve 2213 // compatibility with Go 1, we need to be careful to track which 2214 // headers were live at the time of WriteHeader, so we write the same 2215 // ones, even if the handler modifies them (~erroneously) after the 2216 // first Write. 2217 func TestHeaderToWire(t *testing.T) { 2218 tests := []struct { 2219 name string 2220 handler func(ResponseWriter, *Request) 2221 check func(output string) error 2222 }{ 2223 { 2224 name: "write without Header", 2225 handler: func(rw ResponseWriter, r *Request) { 2226 rw.Write([]byte("hello world")) 2227 }, 2228 check: func(got string) error { 2229 if !strings.Contains(got, "Content-Length:") { 2230 return errors.New("no content-length") 2231 } 2232 if !strings.Contains(got, "Content-Type: text/plain") { 2233 return errors.New("no content-length") 2234 } 2235 return nil 2236 }, 2237 }, 2238 { 2239 name: "Header mutation before write", 2240 handler: func(rw ResponseWriter, r *Request) { 2241 h := rw.Header() 2242 h.Set("Content-Type", "some/type") 2243 rw.Write([]byte("hello world")) 2244 h.Set("Too-Late", "bogus") 2245 }, 2246 check: func(got string) error { 2247 if !strings.Contains(got, "Content-Length:") { 2248 return errors.New("no content-length") 2249 } 2250 if !strings.Contains(got, "Content-Type: some/type") { 2251 return errors.New("wrong content-type") 2252 } 2253 if strings.Contains(got, "Too-Late") { 2254 return errors.New("don't want too-late header") 2255 } 2256 return nil 2257 }, 2258 }, 2259 { 2260 name: "write then useless Header mutation", 2261 handler: func(rw ResponseWriter, r *Request) { 2262 rw.Write([]byte("hello world")) 2263 rw.Header().Set("Too-Late", "Write already wrote headers") 2264 }, 2265 check: func(got string) error { 2266 if strings.Contains(got, "Too-Late") { 2267 return errors.New("header appeared from after WriteHeader") 2268 } 2269 return nil 2270 }, 2271 }, 2272 { 2273 name: "flush then write", 2274 handler: func(rw ResponseWriter, r *Request) { 2275 rw.(Flusher).Flush() 2276 rw.Write([]byte("post-flush")) 2277 rw.Header().Set("Too-Late", "Write already wrote headers") 2278 }, 2279 check: func(got string) error { 2280 if !strings.Contains(got, "Transfer-Encoding: chunked") { 2281 return errors.New("not chunked") 2282 } 2283 if strings.Contains(got, "Too-Late") { 2284 return errors.New("header appeared from after WriteHeader") 2285 } 2286 return nil 2287 }, 2288 }, 2289 { 2290 name: "header then flush", 2291 handler: func(rw ResponseWriter, r *Request) { 2292 rw.Header().Set("Content-Type", "some/type") 2293 rw.(Flusher).Flush() 2294 rw.Write([]byte("post-flush")) 2295 rw.Header().Set("Too-Late", "Write already wrote headers") 2296 }, 2297 check: func(got string) error { 2298 if !strings.Contains(got, "Transfer-Encoding: chunked") { 2299 return errors.New("not chunked") 2300 } 2301 if strings.Contains(got, "Too-Late") { 2302 return errors.New("header appeared from after WriteHeader") 2303 } 2304 if !strings.Contains(got, "Content-Type: some/type") { 2305 return errors.New("wrong content-length") 2306 } 2307 return nil 2308 }, 2309 }, 2310 { 2311 name: "sniff-on-first-write content-type", 2312 handler: func(rw ResponseWriter, r *Request) { 2313 rw.Write([]byte("<html><head></head><body>some html</body></html>")) 2314 rw.Header().Set("Content-Type", "x/wrong") 2315 }, 2316 check: func(got string) error { 2317 if !strings.Contains(got, "Content-Type: text/html") { 2318 return errors.New("wrong content-length; want html") 2319 } 2320 return nil 2321 }, 2322 }, 2323 { 2324 name: "explicit content-type wins", 2325 handler: func(rw ResponseWriter, r *Request) { 2326 rw.Header().Set("Content-Type", "some/type") 2327 rw.Write([]byte("<html><head></head><body>some html</body></html>")) 2328 }, 2329 check: func(got string) error { 2330 if !strings.Contains(got, "Content-Type: some/type") { 2331 return errors.New("wrong content-length; want html") 2332 } 2333 return nil 2334 }, 2335 }, 2336 { 2337 name: "empty handler", 2338 handler: func(rw ResponseWriter, r *Request) { 2339 }, 2340 check: func(got string) error { 2341 if !strings.Contains(got, "Content-Type: text/plain") { 2342 return errors.New("wrong content-length; want text/plain") 2343 } 2344 if !strings.Contains(got, "Content-Length: 0") { 2345 return errors.New("want 0 content-length") 2346 } 2347 return nil 2348 }, 2349 }, 2350 { 2351 name: "only Header, no write", 2352 handler: func(rw ResponseWriter, r *Request) { 2353 rw.Header().Set("Some-Header", "some-value") 2354 }, 2355 check: func(got string) error { 2356 if !strings.Contains(got, "Some-Header") { 2357 return errors.New("didn't get header") 2358 } 2359 return nil 2360 }, 2361 }, 2362 { 2363 name: "WriteHeader call", 2364 handler: func(rw ResponseWriter, r *Request) { 2365 rw.WriteHeader(404) 2366 rw.Header().Set("Too-Late", "some-value") 2367 }, 2368 check: func(got string) error { 2369 if !strings.Contains(got, "404") { 2370 return errors.New("wrong status") 2371 } 2372 if strings.Contains(got, "Some-Header") { 2373 return errors.New("shouldn't have seen Too-Late") 2374 } 2375 return nil 2376 }, 2377 }, 2378 } 2379 for _, tc := range tests { 2380 ht := newHandlerTest(HandlerFunc(tc.handler)) 2381 got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org") 2382 if err := tc.check(got); err != nil { 2383 t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, got) 2384 } 2385 } 2386 } 2387 2388 // goTimeout runs f, failing t if f takes more than ns to complete. 2389 func goTimeout(t *testing.T, d time.Duration, f func()) { 2390 ch := make(chan bool, 2) 2391 timer := time.AfterFunc(d, func() { 2392 t.Errorf("Timeout expired after %v", d) 2393 ch <- true 2394 }) 2395 defer timer.Stop() 2396 go func() { 2397 defer func() { ch <- true }() 2398 f() 2399 }() 2400 <-ch 2401 } 2402 2403 type errorListener struct { 2404 errs []error 2405 } 2406 2407 func (l *errorListener) Accept() (c net.Conn, err error) { 2408 if len(l.errs) == 0 { 2409 return nil, io.EOF 2410 } 2411 err = l.errs[0] 2412 l.errs = l.errs[1:] 2413 return 2414 } 2415 2416 func (l *errorListener) Close() error { 2417 return nil 2418 } 2419 2420 func (l *errorListener) Addr() net.Addr { 2421 return dummyAddr("test-address") 2422 } 2423 2424 func TestAcceptMaxFds(t *testing.T) { 2425 log.SetOutput(ioutil.Discard) // is noisy otherwise 2426 defer log.SetOutput(os.Stderr) 2427 2428 ln := &errorListener{[]error{ 2429 &net.OpError{ 2430 Op: "accept", 2431 Err: syscall.EMFILE, 2432 }}} 2433 err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {}))) 2434 if err != io.EOF { 2435 t.Errorf("got error %v, want EOF", err) 2436 } 2437 } 2438 2439 func TestWriteAfterHijack(t *testing.T) { 2440 req := reqBytes("GET / HTTP/1.1\nHost: golang.org") 2441 var buf bytes.Buffer 2442 wrotec := make(chan bool, 1) 2443 conn := &rwTestConn{ 2444 Reader: bytes.NewReader(req), 2445 Writer: &buf, 2446 closec: make(chan bool, 1), 2447 } 2448 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 2449 conn, bufrw, err := rw.(Hijacker).Hijack() 2450 if err != nil { 2451 t.Error(err) 2452 return 2453 } 2454 go func() { 2455 bufrw.Write([]byte("[hijack-to-bufw]")) 2456 bufrw.Flush() 2457 conn.Write([]byte("[hijack-to-conn]")) 2458 conn.Close() 2459 wrotec <- true 2460 }() 2461 }) 2462 ln := &oneConnListener{conn: conn} 2463 go Serve(ln, handler) 2464 <-conn.closec 2465 <-wrotec 2466 if g, w := buf.String(), "[hijack-to-bufw][hijack-to-conn]"; g != w { 2467 t.Errorf("wrote %q; want %q", g, w) 2468 } 2469 } 2470 2471 func TestDoubleHijack(t *testing.T) { 2472 req := reqBytes("GET / HTTP/1.1\nHost: golang.org") 2473 var buf bytes.Buffer 2474 conn := &rwTestConn{ 2475 Reader: bytes.NewReader(req), 2476 Writer: &buf, 2477 closec: make(chan bool, 1), 2478 } 2479 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 2480 conn, _, err := rw.(Hijacker).Hijack() 2481 if err != nil { 2482 t.Error(err) 2483 return 2484 } 2485 _, _, err = rw.(Hijacker).Hijack() 2486 if err == nil { 2487 t.Errorf("got err = nil; want err != nil") 2488 } 2489 conn.Close() 2490 }) 2491 ln := &oneConnListener{conn: conn} 2492 go Serve(ln, handler) 2493 <-conn.closec 2494 } 2495 2496 // https://golang.org/issue/5955 2497 // Note that this does not test the "request too large" 2498 // exit path from the http server. This is intentional; 2499 // not sending Connection: close is just a minor wire 2500 // optimization and is pointless if dealing with a 2501 // badly behaved client. 2502 func TestHTTP10ConnectionHeader(t *testing.T) { 2503 defer afterTest(t) 2504 2505 mux := NewServeMux() 2506 mux.Handle("/", HandlerFunc(func(resp ResponseWriter, req *Request) {})) 2507 ts := httptest.NewServer(mux) 2508 defer ts.Close() 2509 2510 // net/http uses HTTP/1.1 for requests, so write requests manually 2511 tests := []struct { 2512 req string // raw http request 2513 expect []string // expected Connection header(s) 2514 }{ 2515 { 2516 req: "GET / HTTP/1.0\r\n\r\n", 2517 expect: nil, 2518 }, 2519 { 2520 req: "OPTIONS * HTTP/1.0\r\n\r\n", 2521 expect: nil, 2522 }, 2523 { 2524 req: "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", 2525 expect: []string{"keep-alive"}, 2526 }, 2527 } 2528 2529 for _, tt := range tests { 2530 conn, err := net.Dial("tcp", ts.Listener.Addr().String()) 2531 if err != nil { 2532 t.Fatal("dial err:", err) 2533 } 2534 2535 _, err = fmt.Fprint(conn, tt.req) 2536 if err != nil { 2537 t.Fatal("conn write err:", err) 2538 } 2539 2540 resp, err := ReadResponse(bufio.NewReader(conn), &Request{Method: "GET"}) 2541 if err != nil { 2542 t.Fatal("ReadResponse err:", err) 2543 } 2544 conn.Close() 2545 resp.Body.Close() 2546 2547 got := resp.Header["Connection"] 2548 if !reflect.DeepEqual(got, tt.expect) { 2549 t.Errorf("wrong Connection headers for request %q. Got %q expect %q", tt.req, got, tt.expect) 2550 } 2551 } 2552 } 2553 2554 // See golang.org/issue/5660 2555 func TestServerReaderFromOrder(t *testing.T) { 2556 defer afterTest(t) 2557 pr, pw := io.Pipe() 2558 const size = 3 << 20 2559 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 2560 rw.Header().Set("Content-Type", "text/plain") // prevent sniffing path 2561 done := make(chan bool) 2562 go func() { 2563 io.Copy(rw, pr) 2564 close(done) 2565 }() 2566 time.Sleep(25 * time.Millisecond) // give Copy a chance to break things 2567 n, err := io.Copy(ioutil.Discard, req.Body) 2568 if err != nil { 2569 t.Errorf("handler Copy: %v", err) 2570 return 2571 } 2572 if n != size { 2573 t.Errorf("handler Copy = %d; want %d", n, size) 2574 } 2575 pw.Write([]byte("hi")) 2576 pw.Close() 2577 <-done 2578 })) 2579 defer ts.Close() 2580 2581 req, err := NewRequest("POST", ts.URL, io.LimitReader(neverEnding('a'), size)) 2582 if err != nil { 2583 t.Fatal(err) 2584 } 2585 res, err := DefaultClient.Do(req) 2586 if err != nil { 2587 t.Fatal(err) 2588 } 2589 all, err := ioutil.ReadAll(res.Body) 2590 if err != nil { 2591 t.Fatal(err) 2592 } 2593 res.Body.Close() 2594 if string(all) != "hi" { 2595 t.Errorf("Body = %q; want hi", all) 2596 } 2597 } 2598 2599 // Issue 6157, Issue 6685 2600 func TestCodesPreventingContentTypeAndBody(t *testing.T) { 2601 for _, code := range []int{StatusNotModified, StatusNoContent, StatusContinue} { 2602 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) { 2603 if r.URL.Path == "/header" { 2604 w.Header().Set("Content-Length", "123") 2605 } 2606 w.WriteHeader(code) 2607 if r.URL.Path == "/more" { 2608 w.Write([]byte("stuff")) 2609 } 2610 })) 2611 for _, req := range []string{ 2612 "GET / HTTP/1.0", 2613 "GET /header HTTP/1.0", 2614 "GET /more HTTP/1.0", 2615 "GET / HTTP/1.1", 2616 "GET /header HTTP/1.1", 2617 "GET /more HTTP/1.1", 2618 } { 2619 got := ht.rawResponse(req) 2620 wantStatus := fmt.Sprintf("%d %s", code, StatusText(code)) 2621 if !strings.Contains(got, wantStatus) { 2622 t.Errorf("Code %d: Wanted %q Modified for %q: %s", code, wantStatus, req, got) 2623 } else if strings.Contains(got, "Content-Length") { 2624 t.Errorf("Code %d: Got a Content-Length from %q: %s", code, req, got) 2625 } else if strings.Contains(got, "stuff") { 2626 t.Errorf("Code %d: Response contains a body from %q: %s", code, req, got) 2627 } 2628 } 2629 } 2630 } 2631 2632 func TestContentTypeOkayOn204(t *testing.T) { 2633 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) { 2634 w.Header().Set("Content-Length", "123") // suppressed 2635 w.Header().Set("Content-Type", "foo/bar") 2636 w.WriteHeader(204) 2637 })) 2638 got := ht.rawResponse("GET / HTTP/1.1") 2639 if !strings.Contains(got, "Content-Type: foo/bar") { 2640 t.Errorf("Response = %q; want Content-Type: foo/bar", got) 2641 } 2642 if strings.Contains(got, "Content-Length: 123") { 2643 t.Errorf("Response = %q; don't want a Content-Length", got) 2644 } 2645 } 2646 2647 // Issue 6995 2648 // A server Handler can receive a Request, and then turn around and 2649 // give a copy of that Request.Body out to the Transport (e.g. any 2650 // proxy). So then two people own that Request.Body (both the server 2651 // and the http client), and both think they can close it on failure. 2652 // Therefore, all incoming server requests Bodies need to be thread-safe. 2653 func TestTransportAndServerSharedBodyRace(t *testing.T) { 2654 defer afterTest(t) 2655 2656 const bodySize = 1 << 20 2657 2658 unblockBackend := make(chan bool) 2659 backend := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 2660 io.CopyN(rw, req.Body, bodySize) 2661 <-unblockBackend 2662 })) 2663 defer backend.Close() 2664 2665 backendRespc := make(chan *Response, 1) 2666 proxy := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 2667 req2, _ := NewRequest("POST", backend.URL, req.Body) 2668 req2.ContentLength = bodySize 2669 2670 bresp, err := DefaultClient.Do(req2) 2671 if err != nil { 2672 t.Errorf("Proxy outbound request: %v", err) 2673 return 2674 } 2675 _, err = io.CopyN(ioutil.Discard, bresp.Body, bodySize/2) 2676 if err != nil { 2677 t.Errorf("Proxy copy error: %v", err) 2678 return 2679 } 2680 backendRespc <- bresp // to close later 2681 2682 // Try to cause a race: Both the DefaultTransport and the proxy handler's Server 2683 // will try to read/close req.Body (aka req2.Body) 2684 DefaultTransport.(*Transport).CancelRequest(req2) 2685 rw.Write([]byte("OK")) 2686 })) 2687 defer proxy.Close() 2688 2689 defer close(unblockBackend) 2690 req, _ := NewRequest("POST", proxy.URL, io.LimitReader(neverEnding('a'), bodySize)) 2691 res, err := DefaultClient.Do(req) 2692 if err != nil { 2693 t.Fatalf("Original request: %v", err) 2694 } 2695 2696 // Cleanup, so we don't leak goroutines. 2697 res.Body.Close() 2698 select { 2699 case res := <-backendRespc: 2700 res.Body.Close() 2701 default: 2702 // We failed earlier. (e.g. on DefaultClient.Do(req2)) 2703 } 2704 } 2705 2706 // Test that a hanging Request.Body.Read from another goroutine can't 2707 // cause the Handler goroutine's Request.Body.Close to block. 2708 func TestRequestBodyCloseDoesntBlock(t *testing.T) { 2709 t.Skipf("Skipping known issue; see golang.org/issue/7121") 2710 if testing.Short() { 2711 t.Skip("skipping in -short mode") 2712 } 2713 defer afterTest(t) 2714 2715 readErrCh := make(chan error, 1) 2716 errCh := make(chan error, 2) 2717 2718 server := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 2719 go func(body io.Reader) { 2720 _, err := body.Read(make([]byte, 100)) 2721 readErrCh <- err 2722 }(req.Body) 2723 time.Sleep(500 * time.Millisecond) 2724 })) 2725 defer server.Close() 2726 2727 closeConn := make(chan bool) 2728 defer close(closeConn) 2729 go func() { 2730 conn, err := net.Dial("tcp", server.Listener.Addr().String()) 2731 if err != nil { 2732 errCh <- err 2733 return 2734 } 2735 defer conn.Close() 2736 _, err = conn.Write([]byte("POST / HTTP/1.1\r\nConnection: close\r\nHost: foo\r\nContent-Length: 100000\r\n\r\n")) 2737 if err != nil { 2738 errCh <- err 2739 return 2740 } 2741 // And now just block, making the server block on our 2742 // 100000 bytes of body that will never arrive. 2743 <-closeConn 2744 }() 2745 select { 2746 case err := <-readErrCh: 2747 if err == nil { 2748 t.Error("Read was nil. Expected error.") 2749 } 2750 case err := <-errCh: 2751 t.Error(err) 2752 case <-time.After(5 * time.Second): 2753 t.Error("timeout") 2754 } 2755 } 2756 2757 // test that ResponseWriter implements io.stringWriter. 2758 func TestResponseWriterWriteString(t *testing.T) { 2759 okc := make(chan bool, 1) 2760 ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) { 2761 type stringWriter interface { 2762 WriteString(s string) (n int, err error) 2763 } 2764 _, ok := w.(stringWriter) 2765 okc <- ok 2766 })) 2767 ht.rawResponse("GET / HTTP/1.0") 2768 select { 2769 case ok := <-okc: 2770 if !ok { 2771 t.Error("ResponseWriter did not implement io.stringWriter") 2772 } 2773 default: 2774 t.Error("handler was never called") 2775 } 2776 } 2777 2778 func TestAppendTime(t *testing.T) { 2779 var b [len(TimeFormat)]byte 2780 t1 := time.Date(2013, 9, 21, 15, 41, 0, 0, time.FixedZone("CEST", 2*60*60)) 2781 res := ExportAppendTime(b[:0], t1) 2782 t2, err := ParseTime(string(res)) 2783 if err != nil { 2784 t.Fatalf("Error parsing time: %s", err) 2785 } 2786 if !t1.Equal(t2) { 2787 t.Fatalf("Times differ; expected: %v, got %v (%s)", t1, t2, string(res)) 2788 } 2789 } 2790 2791 func TestServerConnState(t *testing.T) { 2792 defer afterTest(t) 2793 handler := map[string]func(w ResponseWriter, r *Request){ 2794 "/": func(w ResponseWriter, r *Request) { 2795 fmt.Fprintf(w, "Hello.") 2796 }, 2797 "/close": func(w ResponseWriter, r *Request) { 2798 w.Header().Set("Connection", "close") 2799 fmt.Fprintf(w, "Hello.") 2800 }, 2801 "/hijack": func(w ResponseWriter, r *Request) { 2802 c, _, _ := w.(Hijacker).Hijack() 2803 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello.")) 2804 c.Close() 2805 }, 2806 "/hijack-panic": func(w ResponseWriter, r *Request) { 2807 c, _, _ := w.(Hijacker).Hijack() 2808 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nHello.")) 2809 c.Close() 2810 panic("intentional panic") 2811 }, 2812 } 2813 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) { 2814 handler[r.URL.Path](w, r) 2815 })) 2816 defer ts.Close() 2817 2818 var mu sync.Mutex // guard stateLog and connID 2819 var stateLog = map[int][]ConnState{} 2820 var connID = map[net.Conn]int{} 2821 2822 ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0) 2823 ts.Config.ConnState = func(c net.Conn, state ConnState) { 2824 if c == nil { 2825 t.Errorf("nil conn seen in state %s", state) 2826 return 2827 } 2828 mu.Lock() 2829 defer mu.Unlock() 2830 id, ok := connID[c] 2831 if !ok { 2832 id = len(connID) + 1 2833 connID[c] = id 2834 } 2835 stateLog[id] = append(stateLog[id], state) 2836 } 2837 ts.Start() 2838 2839 mustGet(t, ts.URL+"/") 2840 mustGet(t, ts.URL+"/close") 2841 2842 mustGet(t, ts.URL+"/") 2843 mustGet(t, ts.URL+"/", "Connection", "close") 2844 2845 mustGet(t, ts.URL+"/hijack") 2846 mustGet(t, ts.URL+"/hijack-panic") 2847 2848 // New->Closed 2849 { 2850 c, err := net.Dial("tcp", ts.Listener.Addr().String()) 2851 if err != nil { 2852 t.Fatal(err) 2853 } 2854 c.Close() 2855 } 2856 2857 // New->Active->Closed 2858 { 2859 c, err := net.Dial("tcp", ts.Listener.Addr().String()) 2860 if err != nil { 2861 t.Fatal(err) 2862 } 2863 if _, err := io.WriteString(c, "BOGUS REQUEST\r\n\r\n"); err != nil { 2864 t.Fatal(err) 2865 } 2866 c.Close() 2867 } 2868 2869 // New->Idle->Closed 2870 { 2871 c, err := net.Dial("tcp", ts.Listener.Addr().String()) 2872 if err != nil { 2873 t.Fatal(err) 2874 } 2875 if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil { 2876 t.Fatal(err) 2877 } 2878 res, err := ReadResponse(bufio.NewReader(c), nil) 2879 if err != nil { 2880 t.Fatal(err) 2881 } 2882 if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { 2883 t.Fatal(err) 2884 } 2885 c.Close() 2886 } 2887 2888 want := map[int][]ConnState{ 2889 1: {StateNew, StateActive, StateIdle, StateActive, StateClosed}, 2890 2: {StateNew, StateActive, StateIdle, StateActive, StateClosed}, 2891 3: {StateNew, StateActive, StateHijacked}, 2892 4: {StateNew, StateActive, StateHijacked}, 2893 5: {StateNew, StateClosed}, 2894 6: {StateNew, StateActive, StateClosed}, 2895 7: {StateNew, StateActive, StateIdle, StateClosed}, 2896 } 2897 logString := func(m map[int][]ConnState) string { 2898 var b bytes.Buffer 2899 for id, l := range m { 2900 fmt.Fprintf(&b, "Conn %d: ", id) 2901 for _, s := range l { 2902 fmt.Fprintf(&b, "%s ", s) 2903 } 2904 b.WriteString("\n") 2905 } 2906 return b.String() 2907 } 2908 2909 for i := 0; i < 5; i++ { 2910 time.Sleep(time.Duration(i) * 50 * time.Millisecond) 2911 mu.Lock() 2912 match := reflect.DeepEqual(stateLog, want) 2913 mu.Unlock() 2914 if match { 2915 return 2916 } 2917 } 2918 2919 mu.Lock() 2920 t.Errorf("Unexpected events.\nGot log: %s\n Want: %s\n", logString(stateLog), logString(want)) 2921 mu.Unlock() 2922 } 2923 2924 func mustGet(t *testing.T, url string, headers ...string) { 2925 req, err := NewRequest("GET", url, nil) 2926 if err != nil { 2927 t.Fatal(err) 2928 } 2929 for len(headers) > 0 { 2930 req.Header.Add(headers[0], headers[1]) 2931 headers = headers[2:] 2932 } 2933 res, err := DefaultClient.Do(req) 2934 if err != nil { 2935 t.Errorf("Error fetching %s: %v", url, err) 2936 return 2937 } 2938 _, err = ioutil.ReadAll(res.Body) 2939 defer res.Body.Close() 2940 if err != nil { 2941 t.Errorf("Error reading %s: %v", url, err) 2942 } 2943 } 2944 2945 func TestServerKeepAlivesEnabled(t *testing.T) { 2946 defer afterTest(t) 2947 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 2948 ts.Config.SetKeepAlivesEnabled(false) 2949 ts.Start() 2950 defer ts.Close() 2951 res, err := Get(ts.URL) 2952 if err != nil { 2953 t.Fatal(err) 2954 } 2955 defer res.Body.Close() 2956 if !res.Close { 2957 t.Errorf("Body.Close == false; want true") 2958 } 2959 } 2960 2961 // golang.org/issue/7856 2962 func TestServerEmptyBodyRace(t *testing.T) { 2963 defer afterTest(t) 2964 var n int32 2965 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 2966 atomic.AddInt32(&n, 1) 2967 })) 2968 defer ts.Close() 2969 var wg sync.WaitGroup 2970 const reqs = 20 2971 for i := 0; i < reqs; i++ { 2972 wg.Add(1) 2973 go func() { 2974 defer wg.Done() 2975 res, err := Get(ts.URL) 2976 if err != nil { 2977 t.Error(err) 2978 return 2979 } 2980 defer res.Body.Close() 2981 _, err = io.Copy(ioutil.Discard, res.Body) 2982 if err != nil { 2983 t.Error(err) 2984 return 2985 } 2986 }() 2987 } 2988 wg.Wait() 2989 if got := atomic.LoadInt32(&n); got != reqs { 2990 t.Errorf("handler ran %d times; want %d", got, reqs) 2991 } 2992 } 2993 2994 func TestServerConnStateNew(t *testing.T) { 2995 sawNew := false // if the test is buggy, we'll race on this variable. 2996 srv := &Server{ 2997 ConnState: func(c net.Conn, state ConnState) { 2998 if state == StateNew { 2999 sawNew = true // testing that this write isn't racy 3000 } 3001 }, 3002 Handler: HandlerFunc(func(w ResponseWriter, r *Request) {}), // irrelevant 3003 } 3004 srv.Serve(&oneConnListener{ 3005 conn: &rwTestConn{ 3006 Reader: strings.NewReader("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"), 3007 Writer: ioutil.Discard, 3008 }, 3009 }) 3010 if !sawNew { // testing that this read isn't racy 3011 t.Error("StateNew not seen") 3012 } 3013 } 3014 3015 type closeWriteTestConn struct { 3016 rwTestConn 3017 didCloseWrite bool 3018 } 3019 3020 func (c *closeWriteTestConn) CloseWrite() error { 3021 c.didCloseWrite = true 3022 return nil 3023 } 3024 3025 func TestCloseWrite(t *testing.T) { 3026 var srv Server 3027 var testConn closeWriteTestConn 3028 c, err := ExportServerNewConn(&srv, &testConn) 3029 if err != nil { 3030 t.Fatal(err) 3031 } 3032 ExportCloseWriteAndWait(c) 3033 if !testConn.didCloseWrite { 3034 t.Error("didn't see CloseWrite call") 3035 } 3036 } 3037 3038 // This verifies that a handler can Flush and then Hijack. 3039 // 3040 // An similar test crashed once during development, but it was only 3041 // testing this tangentially and temporarily until another TODO was 3042 // fixed. 3043 // 3044 // So add an explicit test for this. 3045 func TestServerFlushAndHijack(t *testing.T) { 3046 defer afterTest(t) 3047 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3048 io.WriteString(w, "Hello, ") 3049 w.(Flusher).Flush() 3050 conn, buf, _ := w.(Hijacker).Hijack() 3051 buf.WriteString("6\r\nworld!\r\n0\r\n\r\n") 3052 if err := buf.Flush(); err != nil { 3053 t.Error(err) 3054 } 3055 if err := conn.Close(); err != nil { 3056 t.Error(err) 3057 } 3058 })) 3059 defer ts.Close() 3060 res, err := Get(ts.URL) 3061 if err != nil { 3062 t.Fatal(err) 3063 } 3064 defer res.Body.Close() 3065 all, err := ioutil.ReadAll(res.Body) 3066 if err != nil { 3067 t.Fatal(err) 3068 } 3069 if want := "Hello, world!"; string(all) != want { 3070 t.Errorf("Got %q; want %q", all, want) 3071 } 3072 } 3073 3074 // golang.org/issue/8534 -- the Server shouldn't reuse a connection 3075 // for keep-alive after it's seen any Write error (e.g. a timeout) on 3076 // that net.Conn. 3077 // 3078 // To test, verify we don't timeout or see fewer unique client 3079 // addresses (== unique connections) than requests. 3080 func TestServerKeepAliveAfterWriteError(t *testing.T) { 3081 if testing.Short() { 3082 t.Skip("skipping in -short mode") 3083 } 3084 defer afterTest(t) 3085 const numReq = 3 3086 addrc := make(chan string, numReq) 3087 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3088 addrc <- r.RemoteAddr 3089 time.Sleep(500 * time.Millisecond) 3090 w.(Flusher).Flush() 3091 })) 3092 ts.Config.WriteTimeout = 250 * time.Millisecond 3093 ts.Start() 3094 defer ts.Close() 3095 3096 errc := make(chan error, numReq) 3097 go func() { 3098 defer close(errc) 3099 for i := 0; i < numReq; i++ { 3100 res, err := Get(ts.URL) 3101 if res != nil { 3102 res.Body.Close() 3103 } 3104 errc <- err 3105 } 3106 }() 3107 3108 timeout := time.NewTimer(numReq * 2 * time.Second) // 4x overkill 3109 defer timeout.Stop() 3110 addrSeen := map[string]bool{} 3111 numOkay := 0 3112 for { 3113 select { 3114 case v := <-addrc: 3115 addrSeen[v] = true 3116 case err, ok := <-errc: 3117 if !ok { 3118 if len(addrSeen) != numReq { 3119 t.Errorf("saw %d unique client addresses; want %d", len(addrSeen), numReq) 3120 } 3121 if numOkay != 0 { 3122 t.Errorf("got %d successful client requests; want 0", numOkay) 3123 } 3124 return 3125 } 3126 if err == nil { 3127 numOkay++ 3128 } 3129 case <-timeout.C: 3130 t.Fatal("timeout waiting for requests to complete") 3131 } 3132 } 3133 } 3134 3135 // Issue 9987: shouldn't add automatic Content-Length (or 3136 // Content-Type) if a Transfer-Encoding was set by the handler. 3137 func TestNoContentLengthIfTransferEncoding(t *testing.T) { 3138 defer afterTest(t) 3139 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 3140 w.Header().Set("Transfer-Encoding", "foo") 3141 io.WriteString(w, "<html>") 3142 })) 3143 defer ts.Close() 3144 c, err := net.Dial("tcp", ts.Listener.Addr().String()) 3145 if err != nil { 3146 t.Fatalf("Dial: %v", err) 3147 } 3148 defer c.Close() 3149 if _, err := io.WriteString(c, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"); err != nil { 3150 t.Fatal(err) 3151 } 3152 bs := bufio.NewScanner(c) 3153 var got bytes.Buffer 3154 for bs.Scan() { 3155 if strings.TrimSpace(bs.Text()) == "" { 3156 break 3157 } 3158 got.WriteString(bs.Text()) 3159 got.WriteByte('\n') 3160 } 3161 if err := bs.Err(); err != nil { 3162 t.Fatal(err) 3163 } 3164 if strings.Contains(got.String(), "Content-Length") { 3165 t.Errorf("Unexpected Content-Length in response headers: %s", got.String()) 3166 } 3167 if strings.Contains(got.String(), "Content-Type") { 3168 t.Errorf("Unexpected Content-Type in response headers: %s", got.String()) 3169 } 3170 } 3171 3172 // tolerate extra CRLF(s) before Request-Line on subsequent requests on a conn 3173 // Issue 10876. 3174 func TestTolerateCRLFBeforeRequestLine(t *testing.T) { 3175 req := []byte("POST / HTTP/1.1\r\nHost: golang.org\r\nContent-Length: 3\r\n\r\nABC" + 3176 "\r\n\r\n" + // <-- this stuff is bogus, but we'll ignore it 3177 "GET / HTTP/1.1\r\nHost: golang.org\r\n\r\n") 3178 var buf bytes.Buffer 3179 conn := &rwTestConn{ 3180 Reader: bytes.NewReader(req), 3181 Writer: &buf, 3182 closec: make(chan bool, 1), 3183 } 3184 ln := &oneConnListener{conn: conn} 3185 numReq := 0 3186 go Serve(ln, HandlerFunc(func(rw ResponseWriter, r *Request) { 3187 numReq++ 3188 })) 3189 <-conn.closec 3190 if numReq != 2 { 3191 t.Errorf("num requests = %d; want 2", numReq) 3192 t.Logf("Res: %s", buf.Bytes()) 3193 } 3194 } 3195 3196 func TestIssue11549_Expect100(t *testing.T) { 3197 req := reqBytes(`PUT /readbody HTTP/1.1 3198 User-Agent: PycURL/7.22.0 3199 Host: 127.0.0.1:9000 3200 Accept: */* 3201 Expect: 100-continue 3202 Content-Length: 10 3203 3204 HelloWorldPUT /noreadbody HTTP/1.1 3205 User-Agent: PycURL/7.22.0 3206 Host: 127.0.0.1:9000 3207 Accept: */* 3208 Expect: 100-continue 3209 Content-Length: 10 3210 3211 GET /should-be-ignored HTTP/1.1 3212 Host: foo 3213 3214 `) 3215 var buf bytes.Buffer 3216 conn := &rwTestConn{ 3217 Reader: bytes.NewReader(req), 3218 Writer: &buf, 3219 closec: make(chan bool, 1), 3220 } 3221 ln := &oneConnListener{conn: conn} 3222 numReq := 0 3223 go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) { 3224 numReq++ 3225 if r.URL.Path == "/readbody" { 3226 ioutil.ReadAll(r.Body) 3227 } 3228 io.WriteString(w, "Hello world!") 3229 })) 3230 <-conn.closec 3231 if numReq != 2 { 3232 t.Errorf("num requests = %d; want 2", numReq) 3233 } 3234 if !strings.Contains(buf.String(), "Connection: close\r\n") { 3235 t.Errorf("expected 'Connection: close' in response; got: %s", buf.String()) 3236 } 3237 } 3238 3239 // If a Handler finishes and there's an unread request body, 3240 // verify the server try to do implicit read on it before replying. 3241 func TestHandlerFinishSkipBigContentLengthRead(t *testing.T) { 3242 conn := &testConn{closec: make(chan bool)} 3243 conn.readBuf.Write([]byte(fmt.Sprintf( 3244 "POST / HTTP/1.1\r\n" + 3245 "Host: test\r\n" + 3246 "Content-Length: 9999999999\r\n" + 3247 "\r\n" + strings.Repeat("a", 1<<20)))) 3248 3249 ls := &oneConnListener{conn} 3250 var inHandlerLen int 3251 go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) { 3252 inHandlerLen = conn.readBuf.Len() 3253 rw.WriteHeader(404) 3254 })) 3255 <-conn.closec 3256 afterHandlerLen := conn.readBuf.Len() 3257 3258 if afterHandlerLen != inHandlerLen { 3259 t.Errorf("unexpected implicit read. Read buffer went from %d -> %d", inHandlerLen, afterHandlerLen) 3260 } 3261 } 3262 3263 func BenchmarkClientServer(b *testing.B) { 3264 b.ReportAllocs() 3265 b.StopTimer() 3266 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) { 3267 fmt.Fprintf(rw, "Hello world.\n") 3268 })) 3269 defer ts.Close() 3270 b.StartTimer() 3271 3272 for i := 0; i < b.N; i++ { 3273 res, err := Get(ts.URL) 3274 if err != nil { 3275 b.Fatal("Get:", err) 3276 } 3277 all, err := ioutil.ReadAll(res.Body) 3278 res.Body.Close() 3279 if err != nil { 3280 b.Fatal("ReadAll:", err) 3281 } 3282 body := string(all) 3283 if body != "Hello world.\n" { 3284 b.Fatal("Got body:", body) 3285 } 3286 } 3287 3288 b.StopTimer() 3289 } 3290 3291 func BenchmarkClientServerParallel4(b *testing.B) { 3292 benchmarkClientServerParallel(b, 4, false) 3293 } 3294 3295 func BenchmarkClientServerParallel64(b *testing.B) { 3296 benchmarkClientServerParallel(b, 64, false) 3297 } 3298 3299 func BenchmarkClientServerParallelTLS4(b *testing.B) { 3300 benchmarkClientServerParallel(b, 4, true) 3301 } 3302 3303 func BenchmarkClientServerParallelTLS64(b *testing.B) { 3304 benchmarkClientServerParallel(b, 64, true) 3305 } 3306 3307 func benchmarkClientServerParallel(b *testing.B, parallelism int, useTLS bool) { 3308 b.ReportAllocs() 3309 ts := httptest.NewUnstartedServer(HandlerFunc(func(rw ResponseWriter, r *Request) { 3310 fmt.Fprintf(rw, "Hello world.\n") 3311 })) 3312 if useTLS { 3313 ts.StartTLS() 3314 } else { 3315 ts.Start() 3316 } 3317 defer ts.Close() 3318 b.ResetTimer() 3319 b.SetParallelism(parallelism) 3320 b.RunParallel(func(pb *testing.PB) { 3321 noVerifyTransport := &Transport{ 3322 TLSClientConfig: &tls.Config{ 3323 InsecureSkipVerify: true, 3324 }, 3325 } 3326 defer noVerifyTransport.CloseIdleConnections() 3327 client := &Client{Transport: noVerifyTransport} 3328 for pb.Next() { 3329 res, err := client.Get(ts.URL) 3330 if err != nil { 3331 b.Logf("Get: %v", err) 3332 continue 3333 } 3334 all, err := ioutil.ReadAll(res.Body) 3335 res.Body.Close() 3336 if err != nil { 3337 b.Logf("ReadAll: %v", err) 3338 continue 3339 } 3340 body := string(all) 3341 if body != "Hello world.\n" { 3342 panic("Got body: " + body) 3343 } 3344 } 3345 }) 3346 } 3347 3348 // A benchmark for profiling the server without the HTTP client code. 3349 // The client code runs in a subprocess. 3350 // 3351 // For use like: 3352 // $ go test -c 3353 // $ ./http.test -test.run=XX -test.bench=BenchmarkServer -test.benchtime=15s -test.cpuprofile=http.prof 3354 // $ go tool pprof http.test http.prof 3355 // (pprof) web 3356 func BenchmarkServer(b *testing.B) { 3357 b.ReportAllocs() 3358 // Child process mode; 3359 if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" { 3360 n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N")) 3361 if err != nil { 3362 panic(err) 3363 } 3364 for i := 0; i < n; i++ { 3365 res, err := Get(url) 3366 if err != nil { 3367 log.Panicf("Get: %v", err) 3368 } 3369 all, err := ioutil.ReadAll(res.Body) 3370 res.Body.Close() 3371 if err != nil { 3372 log.Panicf("ReadAll: %v", err) 3373 } 3374 body := string(all) 3375 if body != "Hello world.\n" { 3376 log.Panicf("Got body: %q", body) 3377 } 3378 } 3379 os.Exit(0) 3380 return 3381 } 3382 3383 var res = []byte("Hello world.\n") 3384 b.StopTimer() 3385 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) { 3386 rw.Header().Set("Content-Type", "text/html; charset=utf-8") 3387 rw.Write(res) 3388 })) 3389 defer ts.Close() 3390 b.StartTimer() 3391 3392 cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer$") 3393 cmd.Env = append([]string{ 3394 fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N), 3395 fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL), 3396 }, os.Environ()...) 3397 out, err := cmd.CombinedOutput() 3398 if err != nil { 3399 b.Errorf("Test failure: %v, with output: %s", err, out) 3400 } 3401 } 3402 3403 // getNoBody wraps Get but closes any Response.Body before returning the response. 3404 func getNoBody(urlStr string) (*Response, error) { 3405 res, err := Get(urlStr) 3406 if err != nil { 3407 return nil, err 3408 } 3409 res.Body.Close() 3410 return res, nil 3411 } 3412 3413 // A benchmark for profiling the client without the HTTP server code. 3414 // The server code runs in a subprocess. 3415 func BenchmarkClient(b *testing.B) { 3416 b.ReportAllocs() 3417 b.StopTimer() 3418 defer afterTest(b) 3419 3420 port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user 3421 if port == "" { 3422 port = "39207" 3423 } 3424 var data = []byte("Hello world.\n") 3425 if server := os.Getenv("TEST_BENCH_SERVER"); server != "" { 3426 // Server process mode. 3427 HandleFunc("/", func(w ResponseWriter, r *Request) { 3428 r.ParseForm() 3429 if r.Form.Get("stop") != "" { 3430 os.Exit(0) 3431 } 3432 w.Header().Set("Content-Type", "text/html; charset=utf-8") 3433 w.Write(data) 3434 }) 3435 log.Fatal(ListenAndServe("localhost:"+port, nil)) 3436 } 3437 3438 // Start server process. 3439 cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkClient$") 3440 cmd.Env = append(os.Environ(), "TEST_BENCH_SERVER=yes") 3441 if err := cmd.Start(); err != nil { 3442 b.Fatalf("subprocess failed to start: %v", err) 3443 } 3444 defer cmd.Process.Kill() 3445 done := make(chan error) 3446 go func() { 3447 done <- cmd.Wait() 3448 }() 3449 3450 // Wait for the server process to respond. 3451 url := "http://localhost:" + port + "/" 3452 for i := 0; i < 100; i++ { 3453 time.Sleep(50 * time.Millisecond) 3454 if _, err := getNoBody(url); err == nil { 3455 break 3456 } 3457 if i == 99 { 3458 b.Fatalf("subprocess does not respond") 3459 } 3460 } 3461 3462 // Do b.N requests to the server. 3463 b.StartTimer() 3464 for i := 0; i < b.N; i++ { 3465 res, err := Get(url) 3466 if err != nil { 3467 b.Fatalf("Get: %v", err) 3468 } 3469 body, err := ioutil.ReadAll(res.Body) 3470 res.Body.Close() 3471 if err != nil { 3472 b.Fatalf("ReadAll: %v", err) 3473 } 3474 if bytes.Compare(body, data) != 0 { 3475 b.Fatalf("Got body: %q", body) 3476 } 3477 } 3478 b.StopTimer() 3479 3480 // Instruct server process to stop. 3481 getNoBody(url + "?stop=yes") 3482 select { 3483 case err := <-done: 3484 if err != nil { 3485 b.Fatalf("subprocess failed: %v", err) 3486 } 3487 case <-time.After(5 * time.Second): 3488 b.Fatalf("subprocess did not stop") 3489 } 3490 } 3491 3492 func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) { 3493 b.ReportAllocs() 3494 req := reqBytes(`GET / HTTP/1.0 3495 Host: golang.org 3496 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 3497 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17 3498 Accept-Encoding: gzip,deflate,sdch 3499 Accept-Language: en-US,en;q=0.8 3500 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 3501 `) 3502 res := []byte("Hello world!\n") 3503 3504 conn := &testConn{ 3505 // testConn.Close will not push into the channel 3506 // if it's full. 3507 closec: make(chan bool, 1), 3508 } 3509 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 3510 rw.Header().Set("Content-Type", "text/html; charset=utf-8") 3511 rw.Write(res) 3512 }) 3513 ln := new(oneConnListener) 3514 for i := 0; i < b.N; i++ { 3515 conn.readBuf.Reset() 3516 conn.writeBuf.Reset() 3517 conn.readBuf.Write(req) 3518 ln.conn = conn 3519 Serve(ln, handler) 3520 <-conn.closec 3521 } 3522 } 3523 3524 // repeatReader reads content count times, then EOFs. 3525 type repeatReader struct { 3526 content []byte 3527 count int 3528 off int 3529 } 3530 3531 func (r *repeatReader) Read(p []byte) (n int, err error) { 3532 if r.count <= 0 { 3533 return 0, io.EOF 3534 } 3535 n = copy(p, r.content[r.off:]) 3536 r.off += n 3537 if r.off == len(r.content) { 3538 r.count-- 3539 r.off = 0 3540 } 3541 return 3542 } 3543 3544 func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) { 3545 b.ReportAllocs() 3546 3547 req := reqBytes(`GET / HTTP/1.1 3548 Host: golang.org 3549 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 3550 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17 3551 Accept-Encoding: gzip,deflate,sdch 3552 Accept-Language: en-US,en;q=0.8 3553 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 3554 `) 3555 res := []byte("Hello world!\n") 3556 3557 conn := &rwTestConn{ 3558 Reader: &repeatReader{content: req, count: b.N}, 3559 Writer: ioutil.Discard, 3560 closec: make(chan bool, 1), 3561 } 3562 handled := 0 3563 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 3564 handled++ 3565 rw.Header().Set("Content-Type", "text/html; charset=utf-8") 3566 rw.Write(res) 3567 }) 3568 ln := &oneConnListener{conn: conn} 3569 go Serve(ln, handler) 3570 <-conn.closec 3571 if b.N != handled { 3572 b.Errorf("b.N=%d but handled %d", b.N, handled) 3573 } 3574 } 3575 3576 // same as above, but representing the most simple possible request 3577 // and handler. Notably: the handler does not call rw.Header(). 3578 func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) { 3579 b.ReportAllocs() 3580 3581 req := reqBytes(`GET / HTTP/1.1 3582 Host: golang.org 3583 `) 3584 res := []byte("Hello world!\n") 3585 3586 conn := &rwTestConn{ 3587 Reader: &repeatReader{content: req, count: b.N}, 3588 Writer: ioutil.Discard, 3589 closec: make(chan bool, 1), 3590 } 3591 handled := 0 3592 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 3593 handled++ 3594 rw.Write(res) 3595 }) 3596 ln := &oneConnListener{conn: conn} 3597 go Serve(ln, handler) 3598 <-conn.closec 3599 if b.N != handled { 3600 b.Errorf("b.N=%d but handled %d", b.N, handled) 3601 } 3602 } 3603 3604 const someResponse = "<html>some response</html>" 3605 3606 // A Response that's just no bigger than 2KB, the buffer-before-chunking threshold. 3607 var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse)) 3608 3609 // Both Content-Type and Content-Length set. Should be no buffering. 3610 func BenchmarkServerHandlerTypeLen(b *testing.B) { 3611 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) { 3612 w.Header().Set("Content-Type", "text/html") 3613 w.Header().Set("Content-Length", strconv.Itoa(len(response))) 3614 w.Write(response) 3615 })) 3616 } 3617 3618 // A Content-Type is set, but no length. No sniffing, but will count the Content-Length. 3619 func BenchmarkServerHandlerNoLen(b *testing.B) { 3620 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) { 3621 w.Header().Set("Content-Type", "text/html") 3622 w.Write(response) 3623 })) 3624 } 3625 3626 // A Content-Length is set, but the Content-Type will be sniffed. 3627 func BenchmarkServerHandlerNoType(b *testing.B) { 3628 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) { 3629 w.Header().Set("Content-Length", strconv.Itoa(len(response))) 3630 w.Write(response) 3631 })) 3632 } 3633 3634 // Neither a Content-Type or Content-Length, so sniffed and counted. 3635 func BenchmarkServerHandlerNoHeader(b *testing.B) { 3636 benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) { 3637 w.Write(response) 3638 })) 3639 } 3640 3641 func benchmarkHandler(b *testing.B, h Handler) { 3642 b.ReportAllocs() 3643 req := reqBytes(`GET / HTTP/1.1 3644 Host: golang.org 3645 `) 3646 conn := &rwTestConn{ 3647 Reader: &repeatReader{content: req, count: b.N}, 3648 Writer: ioutil.Discard, 3649 closec: make(chan bool, 1), 3650 } 3651 handled := 0 3652 handler := HandlerFunc(func(rw ResponseWriter, r *Request) { 3653 handled++ 3654 h.ServeHTTP(rw, r) 3655 }) 3656 ln := &oneConnListener{conn: conn} 3657 go Serve(ln, handler) 3658 <-conn.closec 3659 if b.N != handled { 3660 b.Errorf("b.N=%d but handled %d", b.N, handled) 3661 } 3662 } 3663 3664 func BenchmarkServerHijack(b *testing.B) { 3665 b.ReportAllocs() 3666 req := reqBytes(`GET / HTTP/1.1 3667 Host: golang.org 3668 `) 3669 h := HandlerFunc(func(w ResponseWriter, r *Request) { 3670 conn, _, err := w.(Hijacker).Hijack() 3671 if err != nil { 3672 panic(err) 3673 } 3674 conn.Close() 3675 }) 3676 conn := &rwTestConn{ 3677 Writer: ioutil.Discard, 3678 closec: make(chan bool, 1), 3679 } 3680 ln := &oneConnListener{conn: conn} 3681 for i := 0; i < b.N; i++ { 3682 conn.Reader = bytes.NewReader(req) 3683 ln.conn = conn 3684 Serve(ln, h) 3685 <-conn.closec 3686 } 3687 } 3688