github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/net/http/request_test.go (about) 1 // Copyright 2009 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 package http_test 6 7 import ( 8 "bufio" 9 "bytes" 10 "encoding/base64" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "mime/multipart" 15 . "net/http" 16 "net/http/httptest" 17 "net/url" 18 "os" 19 "reflect" 20 "regexp" 21 "strings" 22 "testing" 23 ) 24 25 func TestQuery(t *testing.T) { 26 req := &Request{Method: "GET"} 27 req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar") 28 if q := req.FormValue("q"); q != "foo" { 29 t.Errorf(`req.FormValue("q") = %q, want "foo"`, q) 30 } 31 } 32 33 func TestPostQuery(t *testing.T) { 34 req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not", 35 strings.NewReader("z=post&both=y&prio=2&empty=")) 36 req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") 37 38 if q := req.FormValue("q"); q != "foo" { 39 t.Errorf(`req.FormValue("q") = %q, want "foo"`, q) 40 } 41 if z := req.FormValue("z"); z != "post" { 42 t.Errorf(`req.FormValue("z") = %q, want "post"`, z) 43 } 44 if bq, found := req.PostForm["q"]; found { 45 t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq) 46 } 47 if bz := req.PostFormValue("z"); bz != "post" { 48 t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz) 49 } 50 if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) { 51 t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs) 52 } 53 if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) { 54 t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both) 55 } 56 if prio := req.FormValue("prio"); prio != "2" { 57 t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio) 58 } 59 if empty := req.FormValue("empty"); empty != "" { 60 t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty) 61 } 62 } 63 64 func TestPatchQuery(t *testing.T) { 65 req, _ := NewRequest("PATCH", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not", 66 strings.NewReader("z=post&both=y&prio=2&empty=")) 67 req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") 68 69 if q := req.FormValue("q"); q != "foo" { 70 t.Errorf(`req.FormValue("q") = %q, want "foo"`, q) 71 } 72 if z := req.FormValue("z"); z != "post" { 73 t.Errorf(`req.FormValue("z") = %q, want "post"`, z) 74 } 75 if bq, found := req.PostForm["q"]; found { 76 t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq) 77 } 78 if bz := req.PostFormValue("z"); bz != "post" { 79 t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz) 80 } 81 if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) { 82 t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs) 83 } 84 if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) { 85 t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both) 86 } 87 if prio := req.FormValue("prio"); prio != "2" { 88 t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio) 89 } 90 if empty := req.FormValue("empty"); empty != "" { 91 t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty) 92 } 93 } 94 95 type stringMap map[string][]string 96 type parseContentTypeTest struct { 97 shouldError bool 98 contentType stringMap 99 } 100 101 var parseContentTypeTests = []parseContentTypeTest{ 102 {false, stringMap{"Content-Type": {"text/plain"}}}, 103 // Empty content type is legal - shoult be treated as 104 // application/octet-stream (RFC 2616, section 7.2.1) 105 {false, stringMap{}}, 106 {true, stringMap{"Content-Type": {"text/plain; boundary="}}}, 107 {false, stringMap{"Content-Type": {"application/unknown"}}}, 108 } 109 110 func TestParseFormUnknownContentType(t *testing.T) { 111 for i, test := range parseContentTypeTests { 112 req := &Request{ 113 Method: "POST", 114 Header: Header(test.contentType), 115 Body: ioutil.NopCloser(strings.NewReader("body")), 116 } 117 err := req.ParseForm() 118 switch { 119 case err == nil && test.shouldError: 120 t.Errorf("test %d should have returned error", i) 121 case err != nil && !test.shouldError: 122 t.Errorf("test %d should not have returned error, got %v", i, err) 123 } 124 } 125 } 126 127 func TestParseFormInitializeOnError(t *testing.T) { 128 nilBody, _ := NewRequest("POST", "http://www.google.com/search?q=foo", nil) 129 tests := []*Request{ 130 nilBody, 131 {Method: "GET", URL: nil}, 132 } 133 for i, req := range tests { 134 err := req.ParseForm() 135 if req.Form == nil { 136 t.Errorf("%d. Form not initialized, error %v", i, err) 137 } 138 if req.PostForm == nil { 139 t.Errorf("%d. PostForm not initialized, error %v", i, err) 140 } 141 } 142 } 143 144 func TestMultipartReader(t *testing.T) { 145 req := &Request{ 146 Method: "POST", 147 Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}}, 148 Body: ioutil.NopCloser(new(bytes.Buffer)), 149 } 150 multipart, err := req.MultipartReader() 151 if multipart == nil { 152 t.Errorf("expected multipart; error: %v", err) 153 } 154 155 req.Header = Header{"Content-Type": {"text/plain"}} 156 multipart, err = req.MultipartReader() 157 if multipart != nil { 158 t.Error("unexpected multipart for text/plain") 159 } 160 } 161 162 func TestParseMultipartForm(t *testing.T) { 163 req := &Request{ 164 Method: "POST", 165 Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}}, 166 Body: ioutil.NopCloser(new(bytes.Buffer)), 167 } 168 err := req.ParseMultipartForm(25) 169 if err == nil { 170 t.Error("expected multipart EOF, got nil") 171 } 172 173 req.Header = Header{"Content-Type": {"text/plain"}} 174 err = req.ParseMultipartForm(25) 175 if err != ErrNotMultipart { 176 t.Error("expected ErrNotMultipart for text/plain") 177 } 178 } 179 180 func TestRedirect(t *testing.T) { 181 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 182 switch r.URL.Path { 183 case "/": 184 w.Header().Set("Location", "/foo/") 185 w.WriteHeader(StatusSeeOther) 186 case "/foo/": 187 fmt.Fprintf(w, "foo") 188 default: 189 w.WriteHeader(StatusBadRequest) 190 } 191 })) 192 defer ts.Close() 193 194 var end = regexp.MustCompile("/foo/$") 195 r, err := Get(ts.URL) 196 if err != nil { 197 t.Fatal(err) 198 } 199 r.Body.Close() 200 url := r.Request.URL.String() 201 if r.StatusCode != 200 || !end.MatchString(url) { 202 t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url) 203 } 204 } 205 206 func TestSetBasicAuth(t *testing.T) { 207 r, _ := NewRequest("GET", "http://example.com/", nil) 208 r.SetBasicAuth("Aladdin", "open sesame") 209 if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e { 210 t.Errorf("got header %q, want %q", g, e) 211 } 212 } 213 214 func TestMultipartRequest(t *testing.T) { 215 // Test that we can read the values and files of a 216 // multipart request with FormValue and FormFile, 217 // and that ParseMultipartForm can be called multiple times. 218 req := newTestMultipartRequest(t) 219 if err := req.ParseMultipartForm(25); err != nil { 220 t.Fatal("ParseMultipartForm first call:", err) 221 } 222 defer req.MultipartForm.RemoveAll() 223 validateTestMultipartContents(t, req, false) 224 if err := req.ParseMultipartForm(25); err != nil { 225 t.Fatal("ParseMultipartForm second call:", err) 226 } 227 validateTestMultipartContents(t, req, false) 228 } 229 230 func TestMultipartRequestAuto(t *testing.T) { 231 // Test that FormValue and FormFile automatically invoke 232 // ParseMultipartForm and return the right values. 233 req := newTestMultipartRequest(t) 234 defer func() { 235 if req.MultipartForm != nil { 236 req.MultipartForm.RemoveAll() 237 } 238 }() 239 validateTestMultipartContents(t, req, true) 240 } 241 242 func TestMissingFileMultipartRequest(t *testing.T) { 243 // Test that FormFile returns an error if 244 // the named file is missing. 245 req := newTestMultipartRequest(t) 246 testMissingFile(t, req) 247 } 248 249 // Test that FormValue invokes ParseMultipartForm. 250 func TestFormValueCallsParseMultipartForm(t *testing.T) { 251 req, _ := NewRequest("POST", "http://www.google.com/", strings.NewReader("z=post")) 252 req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") 253 if req.Form != nil { 254 t.Fatal("Unexpected request Form, want nil") 255 } 256 req.FormValue("z") 257 if req.Form == nil { 258 t.Fatal("ParseMultipartForm not called by FormValue") 259 } 260 } 261 262 // Test that FormFile invokes ParseMultipartForm. 263 func TestFormFileCallsParseMultipartForm(t *testing.T) { 264 req := newTestMultipartRequest(t) 265 if req.Form != nil { 266 t.Fatal("Unexpected request Form, want nil") 267 } 268 req.FormFile("") 269 if req.Form == nil { 270 t.Fatal("ParseMultipartForm not called by FormFile") 271 } 272 } 273 274 // Test that ParseMultipartForm errors if called 275 // after MultipartReader on the same request. 276 func TestParseMultipartFormOrder(t *testing.T) { 277 req := newTestMultipartRequest(t) 278 if _, err := req.MultipartReader(); err != nil { 279 t.Fatalf("MultipartReader: %v", err) 280 } 281 if err := req.ParseMultipartForm(1024); err == nil { 282 t.Fatal("expected an error from ParseMultipartForm after call to MultipartReader") 283 } 284 } 285 286 // Test that MultipartReader errors if called 287 // after ParseMultipartForm on the same request. 288 func TestMultipartReaderOrder(t *testing.T) { 289 req := newTestMultipartRequest(t) 290 if err := req.ParseMultipartForm(25); err != nil { 291 t.Fatalf("ParseMultipartForm: %v", err) 292 } 293 defer req.MultipartForm.RemoveAll() 294 if _, err := req.MultipartReader(); err == nil { 295 t.Fatal("expected an error from MultipartReader after call to ParseMultipartForm") 296 } 297 } 298 299 // Test that FormFile errors if called after 300 // MultipartReader on the same request. 301 func TestFormFileOrder(t *testing.T) { 302 req := newTestMultipartRequest(t) 303 if _, err := req.MultipartReader(); err != nil { 304 t.Fatalf("MultipartReader: %v", err) 305 } 306 if _, _, err := req.FormFile(""); err == nil { 307 t.Fatal("expected an error from FormFile after call to MultipartReader") 308 } 309 } 310 311 var readRequestErrorTests = []struct { 312 in string 313 err error 314 }{ 315 {"GET / HTTP/1.1\r\nheader:foo\r\n\r\n", nil}, 316 {"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF}, 317 {"", io.EOF}, 318 } 319 320 func TestReadRequestErrors(t *testing.T) { 321 for i, tt := range readRequestErrorTests { 322 _, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.in))) 323 if err != tt.err { 324 t.Errorf("%d. got error = %v; want %v", i, err, tt.err) 325 } 326 } 327 } 328 329 var newRequestHostTests = []struct { 330 in, out string 331 }{ 332 {"http://www.example.com/", "www.example.com"}, 333 {"http://www.example.com:8080/", "www.example.com:8080"}, 334 335 {"http://192.168.0.1/", "192.168.0.1"}, 336 {"http://192.168.0.1:8080/", "192.168.0.1:8080"}, 337 338 {"http://[fe80::1]/", "[fe80::1]"}, 339 {"http://[fe80::1]:8080/", "[fe80::1]:8080"}, 340 {"http://[fe80::1%25en0]/", "[fe80::1%en0]"}, 341 {"http://[fe80::1%25en0]:8080/", "[fe80::1%en0]:8080"}, 342 } 343 344 func TestNewRequestHost(t *testing.T) { 345 for i, tt := range newRequestHostTests { 346 req, err := NewRequest("GET", tt.in, nil) 347 if err != nil { 348 t.Errorf("#%v: %v", i, err) 349 continue 350 } 351 if req.Host != tt.out { 352 t.Errorf("got %q; want %q", req.Host, tt.out) 353 } 354 } 355 } 356 357 func TestNewRequestContentLength(t *testing.T) { 358 readByte := func(r io.Reader) io.Reader { 359 var b [1]byte 360 r.Read(b[:]) 361 return r 362 } 363 tests := []struct { 364 r io.Reader 365 want int64 366 }{ 367 {bytes.NewReader([]byte("123")), 3}, 368 {bytes.NewBuffer([]byte("1234")), 4}, 369 {strings.NewReader("12345"), 5}, 370 // Not detected: 371 {struct{ io.Reader }{strings.NewReader("xyz")}, 0}, 372 {io.NewSectionReader(strings.NewReader("x"), 0, 6), 0}, 373 {readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0}, 374 } 375 for _, tt := range tests { 376 req, err := NewRequest("POST", "http://localhost/", tt.r) 377 if err != nil { 378 t.Fatal(err) 379 } 380 if req.ContentLength != tt.want { 381 t.Errorf("ContentLength(%T) = %d; want %d", tt.r, req.ContentLength, tt.want) 382 } 383 } 384 } 385 386 var parseHTTPVersionTests = []struct { 387 vers string 388 major, minor int 389 ok bool 390 }{ 391 {"HTTP/0.9", 0, 9, true}, 392 {"HTTP/1.0", 1, 0, true}, 393 {"HTTP/1.1", 1, 1, true}, 394 {"HTTP/3.14", 3, 14, true}, 395 396 {"HTTP", 0, 0, false}, 397 {"HTTP/one.one", 0, 0, false}, 398 {"HTTP/1.1/", 0, 0, false}, 399 {"HTTP/-1,0", 0, 0, false}, 400 {"HTTP/0,-1", 0, 0, false}, 401 {"HTTP/", 0, 0, false}, 402 {"HTTP/1,1", 0, 0, false}, 403 } 404 405 func TestParseHTTPVersion(t *testing.T) { 406 for _, tt := range parseHTTPVersionTests { 407 major, minor, ok := ParseHTTPVersion(tt.vers) 408 if ok != tt.ok || major != tt.major || minor != tt.minor { 409 type version struct { 410 major, minor int 411 ok bool 412 } 413 t.Errorf("failed to parse %q, expected: %#v, got %#v", tt.vers, version{tt.major, tt.minor, tt.ok}, version{major, minor, ok}) 414 } 415 } 416 } 417 418 type getBasicAuthTest struct { 419 username, password string 420 ok bool 421 } 422 423 type basicAuthCredentialsTest struct { 424 username, password string 425 } 426 427 var getBasicAuthTests = []struct { 428 username, password string 429 ok bool 430 }{ 431 {"Aladdin", "open sesame", true}, 432 {"Aladdin", "open:sesame", true}, 433 {"", "", true}, 434 } 435 436 func TestGetBasicAuth(t *testing.T) { 437 for _, tt := range getBasicAuthTests { 438 r, _ := NewRequest("GET", "http://example.com/", nil) 439 r.SetBasicAuth(tt.username, tt.password) 440 username, password, ok := r.BasicAuth() 441 if ok != tt.ok || username != tt.username || password != tt.password { 442 t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok}, 443 getBasicAuthTest{tt.username, tt.password, tt.ok}) 444 } 445 } 446 // Unauthenticated request. 447 r, _ := NewRequest("GET", "http://example.com/", nil) 448 username, password, ok := r.BasicAuth() 449 if ok { 450 t.Errorf("expected false from BasicAuth when the request is unauthenticated") 451 } 452 want := basicAuthCredentialsTest{"", ""} 453 if username != want.username || password != want.password { 454 t.Errorf("expected credentials: %#v when the request is unauthenticated, got %#v", 455 want, basicAuthCredentialsTest{username, password}) 456 } 457 } 458 459 var parseBasicAuthTests = []struct { 460 header, username, password string 461 ok bool 462 }{ 463 {"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "Aladdin", "open sesame", true}, 464 {"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open:sesame")), "Aladdin", "open:sesame", true}, 465 {"Basic " + base64.StdEncoding.EncodeToString([]byte(":")), "", "", true}, 466 {"Basic" + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false}, 467 {base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false}, 468 {"Basic ", "", "", false}, 469 {"Basic Aladdin:open sesame", "", "", false}, 470 {`Digest username="Aladdin"`, "", "", false}, 471 } 472 473 func TestParseBasicAuth(t *testing.T) { 474 for _, tt := range parseBasicAuthTests { 475 r, _ := NewRequest("GET", "http://example.com/", nil) 476 r.Header.Set("Authorization", tt.header) 477 username, password, ok := r.BasicAuth() 478 if ok != tt.ok || username != tt.username || password != tt.password { 479 t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok}, 480 getBasicAuthTest{tt.username, tt.password, tt.ok}) 481 } 482 } 483 } 484 485 type logWrites struct { 486 t *testing.T 487 dst *[]string 488 } 489 490 func (l logWrites) WriteByte(c byte) error { 491 l.t.Fatalf("unexpected WriteByte call") 492 return nil 493 } 494 495 func (l logWrites) Write(p []byte) (n int, err error) { 496 *l.dst = append(*l.dst, string(p)) 497 return len(p), nil 498 } 499 500 func TestRequestWriteBufferedWriter(t *testing.T) { 501 got := []string{} 502 req, _ := NewRequest("GET", "http://foo.com/", nil) 503 req.Write(logWrites{t, &got}) 504 want := []string{ 505 "GET / HTTP/1.1\r\n", 506 "Host: foo.com\r\n", 507 "User-Agent: " + DefaultUserAgent + "\r\n", 508 "\r\n", 509 } 510 if !reflect.DeepEqual(got, want) { 511 t.Errorf("Writes = %q\n Want = %q", got, want) 512 } 513 } 514 515 func testMissingFile(t *testing.T, req *Request) { 516 f, fh, err := req.FormFile("missing") 517 if f != nil { 518 t.Errorf("FormFile file = %v, want nil", f) 519 } 520 if fh != nil { 521 t.Errorf("FormFile file header = %q, want nil", fh) 522 } 523 if err != ErrMissingFile { 524 t.Errorf("FormFile err = %q, want ErrMissingFile", err) 525 } 526 } 527 528 func newTestMultipartRequest(t *testing.T) *Request { 529 b := strings.NewReader(strings.Replace(message, "\n", "\r\n", -1)) 530 req, err := NewRequest("POST", "/", b) 531 if err != nil { 532 t.Fatal("NewRequest:", err) 533 } 534 ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary) 535 req.Header.Set("Content-type", ctype) 536 return req 537 } 538 539 func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) { 540 if g, e := req.FormValue("texta"), textaValue; g != e { 541 t.Errorf("texta value = %q, want %q", g, e) 542 } 543 if g, e := req.FormValue("textb"), textbValue; g != e { 544 t.Errorf("textb value = %q, want %q", g, e) 545 } 546 if g := req.FormValue("missing"); g != "" { 547 t.Errorf("missing value = %q, want empty string", g) 548 } 549 550 assertMem := func(n string, fd multipart.File) { 551 if _, ok := fd.(*os.File); ok { 552 t.Error(n, " is *os.File, should not be") 553 } 554 } 555 fda := testMultipartFile(t, req, "filea", "filea.txt", fileaContents) 556 defer fda.Close() 557 assertMem("filea", fda) 558 fdb := testMultipartFile(t, req, "fileb", "fileb.txt", filebContents) 559 defer fdb.Close() 560 if allMem { 561 assertMem("fileb", fdb) 562 } else { 563 if _, ok := fdb.(*os.File); !ok { 564 t.Errorf("fileb has unexpected underlying type %T", fdb) 565 } 566 } 567 568 testMissingFile(t, req) 569 } 570 571 func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File { 572 f, fh, err := req.FormFile(key) 573 if err != nil { 574 t.Fatalf("FormFile(%q): %q", key, err) 575 } 576 if fh.Filename != expectFilename { 577 t.Errorf("filename = %q, want %q", fh.Filename, expectFilename) 578 } 579 var b bytes.Buffer 580 _, err = io.Copy(&b, f) 581 if err != nil { 582 t.Fatal("copying contents:", err) 583 } 584 if g := b.String(); g != expectContent { 585 t.Errorf("contents = %q, want %q", g, expectContent) 586 } 587 return f 588 } 589 590 const ( 591 fileaContents = "This is a test file." 592 filebContents = "Another test file." 593 textaValue = "foo" 594 textbValue = "bar" 595 boundary = `MyBoundary` 596 ) 597 598 const message = ` 599 --MyBoundary 600 Content-Disposition: form-data; name="filea"; filename="filea.txt" 601 Content-Type: text/plain 602 603 ` + fileaContents + ` 604 --MyBoundary 605 Content-Disposition: form-data; name="fileb"; filename="fileb.txt" 606 Content-Type: text/plain 607 608 ` + filebContents + ` 609 --MyBoundary 610 Content-Disposition: form-data; name="texta" 611 612 ` + textaValue + ` 613 --MyBoundary 614 Content-Disposition: form-data; name="textb" 615 616 ` + textbValue + ` 617 --MyBoundary-- 618 ` 619 620 func benchmarkReadRequest(b *testing.B, request string) { 621 request = request + "\n" // final \n 622 request = strings.Replace(request, "\n", "\r\n", -1) // expand \n to \r\n 623 b.SetBytes(int64(len(request))) 624 r := bufio.NewReader(&infiniteReader{buf: []byte(request)}) 625 b.ReportAllocs() 626 b.ResetTimer() 627 for i := 0; i < b.N; i++ { 628 _, err := ReadRequest(r) 629 if err != nil { 630 b.Fatalf("failed to read request: %v", err) 631 } 632 } 633 } 634 635 // infiniteReader satisfies Read requests as if the contents of buf 636 // loop indefinitely. 637 type infiniteReader struct { 638 buf []byte 639 offset int 640 } 641 642 func (r *infiniteReader) Read(b []byte) (int, error) { 643 n := copy(b, r.buf[r.offset:]) 644 r.offset = (r.offset + n) % len(r.buf) 645 return n, nil 646 } 647 648 func BenchmarkReadRequestChrome(b *testing.B) { 649 // https://github.com/felixge/node-http-perf/blob/master/fixtures/get.http 650 benchmarkReadRequest(b, `GET / HTTP/1.1 651 Host: localhost:8080 652 Connection: keep-alive 653 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 654 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 655 Accept-Encoding: gzip,deflate,sdch 656 Accept-Language: en-US,en;q=0.8 657 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 658 Cookie: __utma=1.1978842379.1323102373.1323102373.1323102373.1; EPi:NumberOfVisits=1,2012-02-28T13:42:18; CrmSession=5b707226b9563e1bc69084d07a107c98; plushContainerWidth=100%25; plushNoTopMenu=0; hudson_auto_refresh=false 659 `) 660 } 661 662 func BenchmarkReadRequestCurl(b *testing.B) { 663 // curl http://localhost:8080/ 664 benchmarkReadRequest(b, `GET / HTTP/1.1 665 User-Agent: curl/7.27.0 666 Host: localhost:8080 667 Accept: */* 668 `) 669 } 670 671 func BenchmarkReadRequestApachebench(b *testing.B) { 672 // ab -n 1 -c 1 http://localhost:8080/ 673 benchmarkReadRequest(b, `GET / HTTP/1.0 674 Host: localhost:8080 675 User-Agent: ApacheBench/2.3 676 Accept: */* 677 `) 678 } 679 680 func BenchmarkReadRequestSiege(b *testing.B) { 681 // siege -r 1 -c 1 http://localhost:8080/ 682 benchmarkReadRequest(b, `GET / HTTP/1.1 683 Host: localhost:8080 684 Accept: */* 685 Accept-Encoding: gzip 686 User-Agent: JoeDog/1.00 [en] (X11; I; Siege 2.70) 687 Connection: keep-alive 688 `) 689 } 690 691 func BenchmarkReadRequestWrk(b *testing.B) { 692 // wrk -t 1 -r 1 -c 1 http://localhost:8080/ 693 benchmarkReadRequest(b, `GET / HTTP/1.1 694 Host: localhost:8080 695 `) 696 }