Home | History | Annotate | Download | only in http
      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/url"
     17 	"os"
     18 	"reflect"
     19 	"regexp"
     20 	"strings"
     21 	"testing"
     22 )
     23 
     24 func TestQuery(t *testing.T) {
     25 	req := &Request{Method: "GET"}
     26 	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
     27 	if q := req.FormValue("q"); q != "foo" {
     28 		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
     29 	}
     30 }
     31 
     32 func TestParseFormQuery(t *testing.T) {
     33 	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&orphan=nope&empty=not",
     34 		strings.NewReader("z=post&both=y&prio=2&=nokey&orphan;empty=&"))
     35 	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
     36 
     37 	if q := req.FormValue("q"); q != "foo" {
     38 		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
     39 	}
     40 	if z := req.FormValue("z"); z != "post" {
     41 		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
     42 	}
     43 	if bq, found := req.PostForm["q"]; found {
     44 		t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
     45 	}
     46 	if bz := req.PostFormValue("z"); bz != "post" {
     47 		t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
     48 	}
     49 	if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
     50 		t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
     51 	}
     52 	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
     53 		t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
     54 	}
     55 	if prio := req.FormValue("prio"); prio != "2" {
     56 		t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
     57 	}
     58 	if orphan := req.Form["orphan"]; !reflect.DeepEqual(orphan, []string{"", "nope"}) {
     59 		t.Errorf(`req.FormValue("orphan") = %q, want "" (from body)`, orphan)
     60 	}
     61 	if empty := req.Form["empty"]; !reflect.DeepEqual(empty, []string{"", "not"}) {
     62 		t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
     63 	}
     64 	if nokey := req.Form[""]; !reflect.DeepEqual(nokey, []string{"nokey"}) {
     65 		t.Errorf(`req.FormValue("nokey") = %q, want "nokey" (from body)`, nokey)
     66 	}
     67 }
     68 
     69 // Tests that we only parse the form automatically for certain methods.
     70 func TestParseFormQueryMethods(t *testing.T) {
     71 	for _, method := range []string{"POST", "PATCH", "PUT", "FOO"} {
     72 		req, _ := NewRequest(method, "http://www.google.com/search",
     73 			strings.NewReader("foo=bar"))
     74 		req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
     75 		want := "bar"
     76 		if method == "FOO" {
     77 			want = ""
     78 		}
     79 		if got := req.FormValue("foo"); got != want {
     80 			t.Errorf(`for method %s, FormValue("foo") = %q; want %q`, method, got, want)
     81 		}
     82 	}
     83 }
     84 
     85 type stringMap map[string][]string
     86 type parseContentTypeTest struct {
     87 	shouldError bool
     88 	contentType stringMap
     89 }
     90 
     91 var parseContentTypeTests = []parseContentTypeTest{
     92 	{false, stringMap{"Content-Type": {"text/plain"}}},
     93 	// Empty content type is legal - should be treated as
     94 	// application/octet-stream (RFC 2616, section 7.2.1)
     95 	{false, stringMap{}},
     96 	{true, stringMap{"Content-Type": {"text/plain; boundary="}}},
     97 	{false, stringMap{"Content-Type": {"application/unknown"}}},
     98 }
     99 
    100 func TestParseFormUnknownContentType(t *testing.T) {
    101 	for i, test := range parseContentTypeTests {
    102 		req := &Request{
    103 			Method: "POST",
    104 			Header: Header(test.contentType),
    105 			Body:   ioutil.NopCloser(strings.NewReader("body")),
    106 		}
    107 		err := req.ParseForm()
    108 		switch {
    109 		case err == nil && test.shouldError:
    110 			t.Errorf("test %d should have returned error", i)
    111 		case err != nil && !test.shouldError:
    112 			t.Errorf("test %d should not have returned error, got %v", i, err)
    113 		}
    114 	}
    115 }
    116 
    117 func TestParseFormInitializeOnError(t *testing.T) {
    118 	nilBody, _ := NewRequest("POST", "http://www.google.com/search?q=foo", nil)
    119 	tests := []*Request{
    120 		nilBody,
    121 		{Method: "GET", URL: nil},
    122 	}
    123 	for i, req := range tests {
    124 		err := req.ParseForm()
    125 		if req.Form == nil {
    126 			t.Errorf("%d. Form not initialized, error %v", i, err)
    127 		}
    128 		if req.PostForm == nil {
    129 			t.Errorf("%d. PostForm not initialized, error %v", i, err)
    130 		}
    131 	}
    132 }
    133 
    134 func TestMultipartReader(t *testing.T) {
    135 	req := &Request{
    136 		Method: "POST",
    137 		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
    138 		Body:   ioutil.NopCloser(new(bytes.Buffer)),
    139 	}
    140 	multipart, err := req.MultipartReader()
    141 	if multipart == nil {
    142 		t.Errorf("expected multipart; error: %v", err)
    143 	}
    144 
    145 	req.Header = Header{"Content-Type": {"text/plain"}}
    146 	multipart, err = req.MultipartReader()
    147 	if multipart != nil {
    148 		t.Error("unexpected multipart for text/plain")
    149 	}
    150 }
    151 
    152 // Issue 9305: ParseMultipartForm should populate PostForm too
    153 func TestParseMultipartFormPopulatesPostForm(t *testing.T) {
    154 	postData :=
    155 		`--xxx
    156 Content-Disposition: form-data; name="field1"
    157 
    158 value1
    159 --xxx
    160 Content-Disposition: form-data; name="field2"
    161 
    162 value2
    163 --xxx
    164 Content-Disposition: form-data; name="file"; filename="file"
    165 Content-Type: application/octet-stream
    166 Content-Transfer-Encoding: binary
    167 
    168 binary data
    169 --xxx--
    170 `
    171 	req := &Request{
    172 		Method: "POST",
    173 		Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}},
    174 		Body:   ioutil.NopCloser(strings.NewReader(postData)),
    175 	}
    176 
    177 	initialFormItems := map[string]string{
    178 		"language": "Go",
    179 		"name":     "gopher",
    180 		"skill":    "go-ing",
    181 		"field2":   "initial-value2",
    182 	}
    183 
    184 	req.Form = make(url.Values)
    185 	for k, v := range initialFormItems {
    186 		req.Form.Add(k, v)
    187 	}
    188 
    189 	err := req.ParseMultipartForm(10000)
    190 	if err != nil {
    191 		t.Fatalf("unexpected multipart error %v", err)
    192 	}
    193 
    194 	wantForm := url.Values{
    195 		"language": []string{"Go"},
    196 		"name":     []string{"gopher"},
    197 		"skill":    []string{"go-ing"},
    198 		"field1":   []string{"value1"},
    199 		"field2":   []string{"initial-value2", "value2"},
    200 	}
    201 	if !reflect.DeepEqual(req.Form, wantForm) {
    202 		t.Fatalf("req.Form = %v, want %v", req.Form, wantForm)
    203 	}
    204 
    205 	wantPostForm := url.Values{
    206 		"field1": []string{"value1"},
    207 		"field2": []string{"value2"},
    208 	}
    209 	if !reflect.DeepEqual(req.PostForm, wantPostForm) {
    210 		t.Fatalf("req.PostForm = %v, want %v", req.PostForm, wantPostForm)
    211 	}
    212 }
    213 
    214 func TestParseMultipartForm(t *testing.T) {
    215 	req := &Request{
    216 		Method: "POST",
    217 		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
    218 		Body:   ioutil.NopCloser(new(bytes.Buffer)),
    219 	}
    220 	err := req.ParseMultipartForm(25)
    221 	if err == nil {
    222 		t.Error("expected multipart EOF, got nil")
    223 	}
    224 
    225 	req.Header = Header{"Content-Type": {"text/plain"}}
    226 	err = req.ParseMultipartForm(25)
    227 	if err != ErrNotMultipart {
    228 		t.Error("expected ErrNotMultipart for text/plain")
    229 	}
    230 }
    231 
    232 func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) }
    233 func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) }
    234 func testRedirect(t *testing.T, h2 bool) {
    235 	defer afterTest(t)
    236 	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
    237 		switch r.URL.Path {
    238 		case "/":
    239 			w.Header().Set("Location", "/foo/")
    240 			w.WriteHeader(StatusSeeOther)
    241 		case "/foo/":
    242 			fmt.Fprintf(w, "foo")
    243 		default:
    244 			w.WriteHeader(StatusBadRequest)
    245 		}
    246 	}))
    247 	defer cst.close()
    248 
    249 	var end = regexp.MustCompile("/foo/$")
    250 	r, err := cst.c.Get(cst.ts.URL)
    251 	if err != nil {
    252 		t.Fatal(err)
    253 	}
    254 	r.Body.Close()
    255 	url := r.Request.URL.String()
    256 	if r.StatusCode != 200 || !end.MatchString(url) {
    257 		t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
    258 	}
    259 }
    260 
    261 func TestSetBasicAuth(t *testing.T) {
    262 	r, _ := NewRequest("GET", "http://example.com/", nil)
    263 	r.SetBasicAuth("Aladdin", "open sesame")
    264 	if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
    265 		t.Errorf("got header %q, want %q", g, e)
    266 	}
    267 }
    268 
    269 func TestMultipartRequest(t *testing.T) {
    270 	// Test that we can read the values and files of a
    271 	// multipart request with FormValue and FormFile,
    272 	// and that ParseMultipartForm can be called multiple times.
    273 	req := newTestMultipartRequest(t)
    274 	if err := req.ParseMultipartForm(25); err != nil {
    275 		t.Fatal("ParseMultipartForm first call:", err)
    276 	}
    277 	defer req.MultipartForm.RemoveAll()
    278 	validateTestMultipartContents(t, req, false)
    279 	if err := req.ParseMultipartForm(25); err != nil {
    280 		t.Fatal("ParseMultipartForm second call:", err)
    281 	}
    282 	validateTestMultipartContents(t, req, false)
    283 }
    284 
    285 func TestMultipartRequestAuto(t *testing.T) {
    286 	// Test that FormValue and FormFile automatically invoke
    287 	// ParseMultipartForm and return the right values.
    288 	req := newTestMultipartRequest(t)
    289 	defer func() {
    290 		if req.MultipartForm != nil {
    291 			req.MultipartForm.RemoveAll()
    292 		}
    293 	}()
    294 	validateTestMultipartContents(t, req, true)
    295 }
    296 
    297 func TestMissingFileMultipartRequest(t *testing.T) {
    298 	// Test that FormFile returns an error if
    299 	// the named file is missing.
    300 	req := newTestMultipartRequest(t)
    301 	testMissingFile(t, req)
    302 }
    303 
    304 // Test that FormValue invokes ParseMultipartForm.
    305 func TestFormValueCallsParseMultipartForm(t *testing.T) {
    306 	req, _ := NewRequest("POST", "http://www.google.com/", strings.NewReader("z=post"))
    307 	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
    308 	if req.Form != nil {
    309 		t.Fatal("Unexpected request Form, want nil")
    310 	}
    311 	req.FormValue("z")
    312 	if req.Form == nil {
    313 		t.Fatal("ParseMultipartForm not called by FormValue")
    314 	}
    315 }
    316 
    317 // Test that FormFile invokes ParseMultipartForm.
    318 func TestFormFileCallsParseMultipartForm(t *testing.T) {
    319 	req := newTestMultipartRequest(t)
    320 	if req.Form != nil {
    321 		t.Fatal("Unexpected request Form, want nil")
    322 	}
    323 	req.FormFile("")
    324 	if req.Form == nil {
    325 		t.Fatal("ParseMultipartForm not called by FormFile")
    326 	}
    327 }
    328 
    329 // Test that ParseMultipartForm errors if called
    330 // after MultipartReader on the same request.
    331 func TestParseMultipartFormOrder(t *testing.T) {
    332 	req := newTestMultipartRequest(t)
    333 	if _, err := req.MultipartReader(); err != nil {
    334 		t.Fatalf("MultipartReader: %v", err)
    335 	}
    336 	if err := req.ParseMultipartForm(1024); err == nil {
    337 		t.Fatal("expected an error from ParseMultipartForm after call to MultipartReader")
    338 	}
    339 }
    340 
    341 // Test that MultipartReader errors if called
    342 // after ParseMultipartForm on the same request.
    343 func TestMultipartReaderOrder(t *testing.T) {
    344 	req := newTestMultipartRequest(t)
    345 	if err := req.ParseMultipartForm(25); err != nil {
    346 		t.Fatalf("ParseMultipartForm: %v", err)
    347 	}
    348 	defer req.MultipartForm.RemoveAll()
    349 	if _, err := req.MultipartReader(); err == nil {
    350 		t.Fatal("expected an error from MultipartReader after call to ParseMultipartForm")
    351 	}
    352 }
    353 
    354 // Test that FormFile errors if called after
    355 // MultipartReader on the same request.
    356 func TestFormFileOrder(t *testing.T) {
    357 	req := newTestMultipartRequest(t)
    358 	if _, err := req.MultipartReader(); err != nil {
    359 		t.Fatalf("MultipartReader: %v", err)
    360 	}
    361 	if _, _, err := req.FormFile(""); err == nil {
    362 		t.Fatal("expected an error from FormFile after call to MultipartReader")
    363 	}
    364 }
    365 
    366 var readRequestErrorTests = []struct {
    367 	in  string
    368 	err string
    369 
    370 	header Header
    371 }{
    372 	0: {"GET / HTTP/1.1\r\nheader:foo\r\n\r\n", "", Header{"Header": {"foo"}}},
    373 	1: {"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF.Error(), nil},
    374 	2: {"", io.EOF.Error(), nil},
    375 	3: {
    376 		in:  "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n",
    377 		err: "http: method cannot contain a Content-Length",
    378 	},
    379 	4: {
    380 		in:     "HEAD / HTTP/1.1\r\n\r\n",
    381 		header: Header{},
    382 	},
    383 
    384 	// Multiple Content-Length values should either be
    385 	// deduplicated if same or reject otherwise
    386 	// See Issue 16490.
    387 	5: {
    388 		in:  "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 0\r\n\r\nGopher hey\r\n",
    389 		err: "cannot contain multiple Content-Length headers",
    390 	},
    391 	6: {
    392 		in:  "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 6\r\n\r\nGopher\r\n",
    393 		err: "cannot contain multiple Content-Length headers",
    394 	},
    395 	7: {
    396 		in:     "PUT / HTTP/1.1\r\nContent-Length: 6 \r\nContent-Length: 6\r\nContent-Length:6\r\n\r\nGopher\r\n",
    397 		err:    "",
    398 		header: Header{"Content-Length": {"6"}},
    399 	},
    400 	8: {
    401 		in:  "PUT / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 6 \r\n\r\n",
    402 		err: "cannot contain multiple Content-Length headers",
    403 	},
    404 	9: {
    405 		in:  "POST / HTTP/1.1\r\nContent-Length:\r\nContent-Length: 3\r\n\r\n",
    406 		err: "cannot contain multiple Content-Length headers",
    407 	},
    408 	10: {
    409 		in:     "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n",
    410 		header: Header{"Content-Length": {"0"}},
    411 	},
    412 }
    413 
    414 func TestReadRequestErrors(t *testing.T) {
    415 	for i, tt := range readRequestErrorTests {
    416 		req, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.in)))
    417 		if err == nil {
    418 			if tt.err != "" {
    419 				t.Errorf("#%d: got nil err; want %q", i, tt.err)
    420 			}
    421 
    422 			if !reflect.DeepEqual(tt.header, req.Header) {
    423 				t.Errorf("#%d: gotHeader: %q wantHeader: %q", i, req.Header, tt.header)
    424 			}
    425 			continue
    426 		}
    427 
    428 		if tt.err == "" || !strings.Contains(err.Error(), tt.err) {
    429 			t.Errorf("%d: got error = %v; want %v", i, err, tt.err)
    430 		}
    431 	}
    432 }
    433 
    434 var newRequestHostTests = []struct {
    435 	in, out string
    436 }{
    437 	{"http://www.example.com/", "www.example.com"},
    438 	{"http://www.example.com:8080/", "www.example.com:8080"},
    439 
    440 	{"http://192.168.0.1/", "192.168.0.1"},
    441 	{"http://192.168.0.1:8080/", "192.168.0.1:8080"},
    442 	{"http://192.168.0.1:/", "192.168.0.1"},
    443 
    444 	{"http://[fe80::1]/", "[fe80::1]"},
    445 	{"http://[fe80::1]:8080/", "[fe80::1]:8080"},
    446 	{"http://[fe80::1%25en0]/", "[fe80::1%en0]"},
    447 	{"http://[fe80::1%25en0]:8080/", "[fe80::1%en0]:8080"},
    448 	{"http://[fe80::1%25en0]:/", "[fe80::1%en0]"},
    449 }
    450 
    451 func TestNewRequestHost(t *testing.T) {
    452 	for i, tt := range newRequestHostTests {
    453 		req, err := NewRequest("GET", tt.in, nil)
    454 		if err != nil {
    455 			t.Errorf("#%v: %v", i, err)
    456 			continue
    457 		}
    458 		if req.Host != tt.out {
    459 			t.Errorf("got %q; want %q", req.Host, tt.out)
    460 		}
    461 	}
    462 }
    463 
    464 func TestRequestInvalidMethod(t *testing.T) {
    465 	_, err := NewRequest("bad method", "http://foo.com/", nil)
    466 	if err == nil {
    467 		t.Error("expected error from NewRequest with invalid method")
    468 	}
    469 	req, err := NewRequest("GET", "http://foo.example/", nil)
    470 	if err != nil {
    471 		t.Fatal(err)
    472 	}
    473 	req.Method = "bad method"
    474 	_, err = DefaultClient.Do(req)
    475 	if err == nil || !strings.Contains(err.Error(), "invalid method") {
    476 		t.Errorf("Transport error = %v; want invalid method", err)
    477 	}
    478 
    479 	req, err = NewRequest("", "http://foo.com/", nil)
    480 	if err != nil {
    481 		t.Errorf("NewRequest(empty method) = %v; want nil", err)
    482 	} else if req.Method != "GET" {
    483 		t.Errorf("NewRequest(empty method) has method %q; want GET", req.Method)
    484 	}
    485 }
    486 
    487 func TestNewRequestContentLength(t *testing.T) {
    488 	readByte := func(r io.Reader) io.Reader {
    489 		var b [1]byte
    490 		r.Read(b[:])
    491 		return r
    492 	}
    493 	tests := []struct {
    494 		r    io.Reader
    495 		want int64
    496 	}{
    497 		{bytes.NewReader([]byte("123")), 3},
    498 		{bytes.NewBuffer([]byte("1234")), 4},
    499 		{strings.NewReader("12345"), 5},
    500 		{strings.NewReader(""), 0},
    501 		{NoBody, 0},
    502 
    503 		// Not detected. During Go 1.8 we tried to make these set to -1, but
    504 		// due to Issue 18117, we keep these returning 0, even though they're
    505 		// unknown.
    506 		{struct{ io.Reader }{strings.NewReader("xyz")}, 0},
    507 		{io.NewSectionReader(strings.NewReader("x"), 0, 6), 0},
    508 		{readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0},
    509 	}
    510 	for i, tt := range tests {
    511 		req, err := NewRequest("POST", "http://localhost/", tt.r)
    512 		if err != nil {
    513 			t.Fatal(err)
    514 		}
    515 		if req.ContentLength != tt.want {
    516 			t.Errorf("test[%d]: ContentLength(%T) = %d; want %d", i, tt.r, req.ContentLength, tt.want)
    517 		}
    518 	}
    519 }
    520 
    521 var parseHTTPVersionTests = []struct {
    522 	vers         string
    523 	major, minor int
    524 	ok           bool
    525 }{
    526 	{"HTTP/0.9", 0, 9, true},
    527 	{"HTTP/1.0", 1, 0, true},
    528 	{"HTTP/1.1", 1, 1, true},
    529 	{"HTTP/3.14", 3, 14, true},
    530 
    531 	{"HTTP", 0, 0, false},
    532 	{"HTTP/one.one", 0, 0, false},
    533 	{"HTTP/1.1/", 0, 0, false},
    534 	{"HTTP/-1,0", 0, 0, false},
    535 	{"HTTP/0,-1", 0, 0, false},
    536 	{"HTTP/", 0, 0, false},
    537 	{"HTTP/1,1", 0, 0, false},
    538 }
    539 
    540 func TestParseHTTPVersion(t *testing.T) {
    541 	for _, tt := range parseHTTPVersionTests {
    542 		major, minor, ok := ParseHTTPVersion(tt.vers)
    543 		if ok != tt.ok || major != tt.major || minor != tt.minor {
    544 			type version struct {
    545 				major, minor int
    546 				ok           bool
    547 			}
    548 			t.Errorf("failed to parse %q, expected: %#v, got %#v", tt.vers, version{tt.major, tt.minor, tt.ok}, version{major, minor, ok})
    549 		}
    550 	}
    551 }
    552 
    553 type getBasicAuthTest struct {
    554 	username, password string
    555 	ok                 bool
    556 }
    557 
    558 type basicAuthCredentialsTest struct {
    559 	username, password string
    560 }
    561 
    562 var getBasicAuthTests = []struct {
    563 	username, password string
    564 	ok                 bool
    565 }{
    566 	{"Aladdin", "open sesame", true},
    567 	{"Aladdin", "open:sesame", true},
    568 	{"", "", true},
    569 }
    570 
    571 func TestGetBasicAuth(t *testing.T) {
    572 	for _, tt := range getBasicAuthTests {
    573 		r, _ := NewRequest("GET", "http://example.com/", nil)
    574 		r.SetBasicAuth(tt.username, tt.password)
    575 		username, password, ok := r.BasicAuth()
    576 		if ok != tt.ok || username != tt.username || password != tt.password {
    577 			t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok},
    578 				getBasicAuthTest{tt.username, tt.password, tt.ok})
    579 		}
    580 	}
    581 	// Unauthenticated request.
    582 	r, _ := NewRequest("GET", "http://example.com/", nil)
    583 	username, password, ok := r.BasicAuth()
    584 	if ok {
    585 		t.Errorf("expected false from BasicAuth when the request is unauthenticated")
    586 	}
    587 	want := basicAuthCredentialsTest{"", ""}
    588 	if username != want.username || password != want.password {
    589 		t.Errorf("expected credentials: %#v when the request is unauthenticated, got %#v",
    590 			want, basicAuthCredentialsTest{username, password})
    591 	}
    592 }
    593 
    594 var parseBasicAuthTests = []struct {
    595 	header, username, password string
    596 	ok                         bool
    597 }{
    598 	{"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "Aladdin", "open sesame", true},
    599 	{"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open:sesame")), "Aladdin", "open:sesame", true},
    600 	{"Basic " + base64.StdEncoding.EncodeToString([]byte(":")), "", "", true},
    601 	{"Basic" + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false},
    602 	{base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false},
    603 	{"Basic ", "", "", false},
    604 	{"Basic Aladdin:open sesame", "", "", false},
    605 	{`Digest username="Aladdin"`, "", "", false},
    606 }
    607 
    608 func TestParseBasicAuth(t *testing.T) {
    609 	for _, tt := range parseBasicAuthTests {
    610 		r, _ := NewRequest("GET", "http://example.com/", nil)
    611 		r.Header.Set("Authorization", tt.header)
    612 		username, password, ok := r.BasicAuth()
    613 		if ok != tt.ok || username != tt.username || password != tt.password {
    614 			t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok},
    615 				getBasicAuthTest{tt.username, tt.password, tt.ok})
    616 		}
    617 	}
    618 }
    619 
    620 type logWrites struct {
    621 	t   *testing.T
    622 	dst *[]string
    623 }
    624 
    625 func (l logWrites) WriteByte(c byte) error {
    626 	l.t.Fatalf("unexpected WriteByte call")
    627 	return nil
    628 }
    629 
    630 func (l logWrites) Write(p []byte) (n int, err error) {
    631 	*l.dst = append(*l.dst, string(p))
    632 	return len(p), nil
    633 }
    634 
    635 func TestRequestWriteBufferedWriter(t *testing.T) {
    636 	got := []string{}
    637 	req, _ := NewRequest("GET", "http://foo.com/", nil)
    638 	req.Write(logWrites{t, &got})
    639 	want := []string{
    640 		"GET / HTTP/1.1\r\n",
    641 		"Host: foo.com\r\n",
    642 		"User-Agent: " + DefaultUserAgent + "\r\n",
    643 		"\r\n",
    644 	}
    645 	if !reflect.DeepEqual(got, want) {
    646 		t.Errorf("Writes = %q\n  Want = %q", got, want)
    647 	}
    648 }
    649 
    650 func TestRequestBadHost(t *testing.T) {
    651 	got := []string{}
    652 	req, err := NewRequest("GET", "http://foo/after", nil)
    653 	if err != nil {
    654 		t.Fatal(err)
    655 	}
    656 	req.Host = "foo.com with spaces"
    657 	req.URL.Host = "foo.com with spaces"
    658 	req.Write(logWrites{t, &got})
    659 	want := []string{
    660 		"GET /after HTTP/1.1\r\n",
    661 		"Host: foo.com\r\n",
    662 		"User-Agent: " + DefaultUserAgent + "\r\n",
    663 		"\r\n",
    664 	}
    665 	if !reflect.DeepEqual(got, want) {
    666 		t.Errorf("Writes = %q\n  Want = %q", got, want)
    667 	}
    668 }
    669 
    670 func TestStarRequest(t *testing.T) {
    671 	req, err := ReadRequest(bufio.NewReader(strings.NewReader("M-SEARCH * HTTP/1.1\r\n\r\n")))
    672 	if err != nil {
    673 		return
    674 	}
    675 	if req.ContentLength != 0 {
    676 		t.Errorf("ContentLength = %d; want 0", req.ContentLength)
    677 	}
    678 	if req.Body == nil {
    679 		t.Errorf("Body = nil; want non-nil")
    680 	}
    681 
    682 	// Request.Write has Client semantics for Body/ContentLength,
    683 	// where ContentLength 0 means unknown if Body is non-nil, and
    684 	// thus chunking will happen unless we change semantics and
    685 	// signal that we want to serialize it as exactly zero.  The
    686 	// only way to do that for outbound requests is with a nil
    687 	// Body:
    688 	clientReq := *req
    689 	clientReq.Body = nil
    690 
    691 	var out bytes.Buffer
    692 	if err := clientReq.Write(&out); err != nil {
    693 		t.Fatal(err)
    694 	}
    695 
    696 	if strings.Contains(out.String(), "chunked") {
    697 		t.Error("wrote chunked request; want no body")
    698 	}
    699 	back, err := ReadRequest(bufio.NewReader(bytes.NewReader(out.Bytes())))
    700 	if err != nil {
    701 		t.Fatal(err)
    702 	}
    703 	// Ignore the Headers (the User-Agent breaks the deep equal,
    704 	// but we don't care about it)
    705 	req.Header = nil
    706 	back.Header = nil
    707 	if !reflect.DeepEqual(req, back) {
    708 		t.Errorf("Original request doesn't match Request read back.")
    709 		t.Logf("Original: %#v", req)
    710 		t.Logf("Original.URL: %#v", req.URL)
    711 		t.Logf("Wrote: %s", out.Bytes())
    712 		t.Logf("Read back (doesn't match Original): %#v", back)
    713 	}
    714 }
    715 
    716 type responseWriterJustWriter struct {
    717 	io.Writer
    718 }
    719 
    720 func (responseWriterJustWriter) Header() Header  { panic("should not be called") }
    721 func (responseWriterJustWriter) WriteHeader(int) { panic("should not be called") }
    722 
    723 // delayedEOFReader never returns (n > 0, io.EOF), instead putting
    724 // off the io.EOF until a subsequent Read call.
    725 type delayedEOFReader struct {
    726 	r io.Reader
    727 }
    728 
    729 func (dr delayedEOFReader) Read(p []byte) (n int, err error) {
    730 	n, err = dr.r.Read(p)
    731 	if n > 0 && err == io.EOF {
    732 		err = nil
    733 	}
    734 	return
    735 }
    736 
    737 func TestIssue10884_MaxBytesEOF(t *testing.T) {
    738 	dst := ioutil.Discard
    739 	_, err := io.Copy(dst, MaxBytesReader(
    740 		responseWriterJustWriter{dst},
    741 		ioutil.NopCloser(delayedEOFReader{strings.NewReader("12345")}),
    742 		5))
    743 	if err != nil {
    744 		t.Fatal(err)
    745 	}
    746 }
    747 
    748 // Issue 14981: MaxBytesReader's return error wasn't sticky. It
    749 // doesn't technically need to be, but people expected it to be.
    750 func TestMaxBytesReaderStickyError(t *testing.T) {
    751 	isSticky := func(r io.Reader) error {
    752 		var log bytes.Buffer
    753 		buf := make([]byte, 1000)
    754 		var firstErr error
    755 		for {
    756 			n, err := r.Read(buf)
    757 			fmt.Fprintf(&log, "Read(%d) = %d, %v\n", len(buf), n, err)
    758 			if err == nil {
    759 				continue
    760 			}
    761 			if firstErr == nil {
    762 				firstErr = err
    763 				continue
    764 			}
    765 			if !reflect.DeepEqual(err, firstErr) {
    766 				return fmt.Errorf("non-sticky error. got log:\n%s", log.Bytes())
    767 			}
    768 			t.Logf("Got log: %s", log.Bytes())
    769 			return nil
    770 		}
    771 	}
    772 	tests := [...]struct {
    773 		readable int
    774 		limit    int64
    775 	}{
    776 		0: {99, 100},
    777 		1: {100, 100},
    778 		2: {101, 100},
    779 	}
    780 	for i, tt := range tests {
    781 		rc := MaxBytesReader(nil, ioutil.NopCloser(bytes.NewReader(make([]byte, tt.readable))), tt.limit)
    782 		if err := isSticky(rc); err != nil {
    783 			t.Errorf("%d. error: %v", i, err)
    784 		}
    785 	}
    786 }
    787 
    788 // verify that NewRequest sets Request.GetBody and that it works
    789 func TestNewRequestGetBody(t *testing.T) {
    790 	tests := []struct {
    791 		r io.Reader
    792 	}{
    793 		{r: strings.NewReader("hello")},
    794 		{r: bytes.NewReader([]byte("hello"))},
    795 		{r: bytes.NewBuffer([]byte("hello"))},
    796 	}
    797 	for i, tt := range tests {
    798 		req, err := NewRequest("POST", "http://foo.tld/", tt.r)
    799 		if err != nil {
    800 			t.Errorf("test[%d]: %v", i, err)
    801 			continue
    802 		}
    803 		if req.Body == nil {
    804 			t.Errorf("test[%d]: Body = nil", i)
    805 			continue
    806 		}
    807 		if req.GetBody == nil {
    808 			t.Errorf("test[%d]: GetBody = nil", i)
    809 			continue
    810 		}
    811 		slurp1, err := ioutil.ReadAll(req.Body)
    812 		if err != nil {
    813 			t.Errorf("test[%d]: ReadAll(Body) = %v", i, err)
    814 		}
    815 		newBody, err := req.GetBody()
    816 		if err != nil {
    817 			t.Errorf("test[%d]: GetBody = %v", i, err)
    818 		}
    819 		slurp2, err := ioutil.ReadAll(newBody)
    820 		if err != nil {
    821 			t.Errorf("test[%d]: ReadAll(GetBody()) = %v", i, err)
    822 		}
    823 		if string(slurp1) != string(slurp2) {
    824 			t.Errorf("test[%d]: Body %q != GetBody %q", i, slurp1, slurp2)
    825 		}
    826 	}
    827 }
    828 
    829 func testMissingFile(t *testing.T, req *Request) {
    830 	f, fh, err := req.FormFile("missing")
    831 	if f != nil {
    832 		t.Errorf("FormFile file = %v, want nil", f)
    833 	}
    834 	if fh != nil {
    835 		t.Errorf("FormFile file header = %q, want nil", fh)
    836 	}
    837 	if err != ErrMissingFile {
    838 		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
    839 	}
    840 }
    841 
    842 func newTestMultipartRequest(t *testing.T) *Request {
    843 	b := strings.NewReader(strings.Replace(message, "\n", "\r\n", -1))
    844 	req, err := NewRequest("POST", "/", b)
    845 	if err != nil {
    846 		t.Fatal("NewRequest:", err)
    847 	}
    848 	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
    849 	req.Header.Set("Content-type", ctype)
    850 	return req
    851 }
    852 
    853 func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
    854 	if g, e := req.FormValue("texta"), textaValue; g != e {
    855 		t.Errorf("texta value = %q, want %q", g, e)
    856 	}
    857 	if g, e := req.FormValue("textb"), textbValue; g != e {
    858 		t.Errorf("textb value = %q, want %q", g, e)
    859 	}
    860 	if g := req.FormValue("missing"); g != "" {
    861 		t.Errorf("missing value = %q, want empty string", g)
    862 	}
    863 
    864 	assertMem := func(n string, fd multipart.File) {
    865 		if _, ok := fd.(*os.File); ok {
    866 			t.Error(n, " is *os.File, should not be")
    867 		}
    868 	}
    869 	fda := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
    870 	defer fda.Close()
    871 	assertMem("filea", fda)
    872 	fdb := testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
    873 	defer fdb.Close()
    874 	if allMem {
    875 		assertMem("fileb", fdb)
    876 	} else {
    877 		if _, ok := fdb.(*os.File); !ok {
    878 			t.Errorf("fileb has unexpected underlying type %T", fdb)
    879 		}
    880 	}
    881 
    882 	testMissingFile(t, req)
    883 }
    884 
    885 func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
    886 	f, fh, err := req.FormFile(key)
    887 	if err != nil {
    888 		t.Fatalf("FormFile(%q): %q", key, err)
    889 	}
    890 	if fh.Filename != expectFilename {
    891 		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
    892 	}
    893 	var b bytes.Buffer
    894 	_, err = io.Copy(&b, f)
    895 	if err != nil {
    896 		t.Fatal("copying contents:", err)
    897 	}
    898 	if g := b.String(); g != expectContent {
    899 		t.Errorf("contents = %q, want %q", g, expectContent)
    900 	}
    901 	return f
    902 }
    903 
    904 const (
    905 	fileaContents = "This is a test file."
    906 	filebContents = "Another test file."
    907 	textaValue    = "foo"
    908 	textbValue    = "bar"
    909 	boundary      = `MyBoundary`
    910 )
    911 
    912 const message = `
    913 --MyBoundary
    914 Content-Disposition: form-data; name="filea"; filename="filea.txt"
    915 Content-Type: text/plain
    916 
    917 ` + fileaContents + `
    918 --MyBoundary
    919 Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
    920 Content-Type: text/plain
    921 
    922 ` + filebContents + `
    923 --MyBoundary
    924 Content-Disposition: form-data; name="texta"
    925 
    926 ` + textaValue + `
    927 --MyBoundary
    928 Content-Disposition: form-data; name="textb"
    929 
    930 ` + textbValue + `
    931 --MyBoundary--
    932 `
    933 
    934 func benchmarkReadRequest(b *testing.B, request string) {
    935 	request = request + "\n"                             // final \n
    936 	request = strings.Replace(request, "\n", "\r\n", -1) // expand \n to \r\n
    937 	b.SetBytes(int64(len(request)))
    938 	r := bufio.NewReader(&infiniteReader{buf: []byte(request)})
    939 	b.ReportAllocs()
    940 	b.ResetTimer()
    941 	for i := 0; i < b.N; i++ {
    942 		_, err := ReadRequest(r)
    943 		if err != nil {
    944 			b.Fatalf("failed to read request: %v", err)
    945 		}
    946 	}
    947 }
    948 
    949 // infiniteReader satisfies Read requests as if the contents of buf
    950 // loop indefinitely.
    951 type infiniteReader struct {
    952 	buf    []byte
    953 	offset int
    954 }
    955 
    956 func (r *infiniteReader) Read(b []byte) (int, error) {
    957 	n := copy(b, r.buf[r.offset:])
    958 	r.offset = (r.offset + n) % len(r.buf)
    959 	return n, nil
    960 }
    961 
    962 func BenchmarkReadRequestChrome(b *testing.B) {
    963 	// https://github.com/felixge/node-http-perf/blob/master/fixtures/get.http
    964 	benchmarkReadRequest(b, `GET / HTTP/1.1
    965 Host: localhost:8080
    966 Connection: keep-alive
    967 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    968 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
    969 Accept-Encoding: gzip,deflate,sdch
    970 Accept-Language: en-US,en;q=0.8
    971 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
    972 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
    973 `)
    974 }
    975 
    976 func BenchmarkReadRequestCurl(b *testing.B) {
    977 	// curl http://localhost:8080/
    978 	benchmarkReadRequest(b, `GET / HTTP/1.1
    979 User-Agent: curl/7.27.0
    980 Host: localhost:8080
    981 Accept: */*
    982 `)
    983 }
    984 
    985 func BenchmarkReadRequestApachebench(b *testing.B) {
    986 	// ab -n 1 -c 1 http://localhost:8080/
    987 	benchmarkReadRequest(b, `GET / HTTP/1.0
    988 Host: localhost:8080
    989 User-Agent: ApacheBench/2.3
    990 Accept: */*
    991 `)
    992 }
    993 
    994 func BenchmarkReadRequestSiege(b *testing.B) {
    995 	// siege -r 1 -c 1 http://localhost:8080/
    996 	benchmarkReadRequest(b, `GET / HTTP/1.1
    997 Host: localhost:8080
    998 Accept: */*
    999 Accept-Encoding: gzip
   1000 User-Agent: JoeDog/1.00 [en] (X11; I; Siege 2.70)
   1001 Connection: keep-alive
   1002 `)
   1003 }
   1004 
   1005 func BenchmarkReadRequestWrk(b *testing.B) {
   1006 	// wrk -t 1 -r 1 -c 1 http://localhost:8080/
   1007 	benchmarkReadRequest(b, `GET / HTTP/1.1
   1008 Host: localhost:8080
   1009 `)
   1010 }
   1011