github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/net/http/client_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 // Tests for client.go 6 7 package http_test 8 9 import ( 10 "bytes" 11 "crypto/tls" 12 "crypto/x509" 13 "encoding/base64" 14 "errors" 15 "fmt" 16 "io" 17 "io/ioutil" 18 "log" 19 "net" 20 . "net/http" 21 "net/http/httptest" 22 "net/url" 23 "strconv" 24 "strings" 25 "sync" 26 "testing" 27 "time" 28 ) 29 30 var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 31 w.Header().Set("Last-Modified", "sometime") 32 fmt.Fprintf(w, "User-agent: go\nDisallow: /something/") 33 }) 34 35 // pedanticReadAll works like ioutil.ReadAll but additionally 36 // verifies that r obeys the documented io.Reader contract. 37 func pedanticReadAll(r io.Reader) (b []byte, err error) { 38 var bufa [64]byte 39 buf := bufa[:] 40 for { 41 n, err := r.Read(buf) 42 if n == 0 && err == nil { 43 return nil, fmt.Errorf("Read: n=0 with err=nil") 44 } 45 b = append(b, buf[:n]...) 46 if err == io.EOF { 47 n, err := r.Read(buf) 48 if n != 0 || err != io.EOF { 49 return nil, fmt.Errorf("Read: n=%d err=%#v after EOF", n, err) 50 } 51 return b, nil 52 } 53 if err != nil { 54 return b, err 55 } 56 } 57 } 58 59 type chanWriter chan string 60 61 func (w chanWriter) Write(p []byte) (n int, err error) { 62 w <- string(p) 63 return len(p), nil 64 } 65 66 func TestClient(t *testing.T) { 67 defer afterTest(t) 68 ts := httptest.NewServer(robotsTxtHandler) 69 defer ts.Close() 70 71 r, err := Get(ts.URL) 72 var b []byte 73 if err == nil { 74 b, err = pedanticReadAll(r.Body) 75 r.Body.Close() 76 } 77 if err != nil { 78 t.Error(err) 79 } else if s := string(b); !strings.HasPrefix(s, "User-agent:") { 80 t.Errorf("Incorrect page body (did not begin with User-agent): %q", s) 81 } 82 } 83 84 func TestClientHead_h1(t *testing.T) { testClientHead(t, h1Mode) } 85 func TestClientHead_h2(t *testing.T) { testClientHead(t, h2Mode) } 86 87 func testClientHead(t *testing.T, h2 bool) { 88 defer afterTest(t) 89 cst := newClientServerTest(t, h2, robotsTxtHandler) 90 defer cst.close() 91 92 r, err := cst.c.Head(cst.ts.URL) 93 if err != nil { 94 t.Fatal(err) 95 } 96 if _, ok := r.Header["Last-Modified"]; !ok { 97 t.Error("Last-Modified header not found.") 98 } 99 } 100 101 type recordingTransport struct { 102 req *Request 103 } 104 105 func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error) { 106 t.req = req 107 return nil, errors.New("dummy impl") 108 } 109 110 func TestGetRequestFormat(t *testing.T) { 111 defer afterTest(t) 112 tr := &recordingTransport{} 113 client := &Client{Transport: tr} 114 url := "http://dummy.faketld/" 115 client.Get(url) // Note: doesn't hit network 116 if tr.req.Method != "GET" { 117 t.Errorf("expected method %q; got %q", "GET", tr.req.Method) 118 } 119 if tr.req.URL.String() != url { 120 t.Errorf("expected URL %q; got %q", url, tr.req.URL.String()) 121 } 122 if tr.req.Header == nil { 123 t.Errorf("expected non-nil request Header") 124 } 125 } 126 127 func TestPostRequestFormat(t *testing.T) { 128 defer afterTest(t) 129 tr := &recordingTransport{} 130 client := &Client{Transport: tr} 131 132 url := "http://dummy.faketld/" 133 json := `{"key":"value"}` 134 b := strings.NewReader(json) 135 client.Post(url, "application/json", b) // Note: doesn't hit network 136 137 if tr.req.Method != "POST" { 138 t.Errorf("got method %q, want %q", tr.req.Method, "POST") 139 } 140 if tr.req.URL.String() != url { 141 t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) 142 } 143 if tr.req.Header == nil { 144 t.Fatalf("expected non-nil request Header") 145 } 146 if tr.req.Close { 147 t.Error("got Close true, want false") 148 } 149 if g, e := tr.req.ContentLength, int64(len(json)); g != e { 150 t.Errorf("got ContentLength %d, want %d", g, e) 151 } 152 } 153 154 func TestPostFormRequestFormat(t *testing.T) { 155 defer afterTest(t) 156 tr := &recordingTransport{} 157 client := &Client{Transport: tr} 158 159 urlStr := "http://dummy.faketld/" 160 form := make(url.Values) 161 form.Set("foo", "bar") 162 form.Add("foo", "bar2") 163 form.Set("bar", "baz") 164 client.PostForm(urlStr, form) // Note: doesn't hit network 165 166 if tr.req.Method != "POST" { 167 t.Errorf("got method %q, want %q", tr.req.Method, "POST") 168 } 169 if tr.req.URL.String() != urlStr { 170 t.Errorf("got URL %q, want %q", tr.req.URL.String(), urlStr) 171 } 172 if tr.req.Header == nil { 173 t.Fatalf("expected non-nil request Header") 174 } 175 if g, e := tr.req.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; g != e { 176 t.Errorf("got Content-Type %q, want %q", g, e) 177 } 178 if tr.req.Close { 179 t.Error("got Close true, want false") 180 } 181 // Depending on map iteration, body can be either of these. 182 expectedBody := "foo=bar&foo=bar2&bar=baz" 183 expectedBody1 := "bar=baz&foo=bar&foo=bar2" 184 if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e { 185 t.Errorf("got ContentLength %d, want %d", g, e) 186 } 187 bodyb, err := ioutil.ReadAll(tr.req.Body) 188 if err != nil { 189 t.Fatalf("ReadAll on req.Body: %v", err) 190 } 191 if g := string(bodyb); g != expectedBody && g != expectedBody1 { 192 t.Errorf("got body %q, want %q or %q", g, expectedBody, expectedBody1) 193 } 194 } 195 196 func TestClientRedirects(t *testing.T) { 197 defer afterTest(t) 198 var ts *httptest.Server 199 ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 200 n, _ := strconv.Atoi(r.FormValue("n")) 201 // Test Referer header. (7 is arbitrary position to test at) 202 if n == 7 { 203 if g, e := r.Referer(), ts.URL+"/?n=6"; e != g { 204 t.Errorf("on request ?n=7, expected referer of %q; got %q", e, g) 205 } 206 } 207 if n < 15 { 208 Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusFound) 209 return 210 } 211 fmt.Fprintf(w, "n=%d", n) 212 })) 213 defer ts.Close() 214 215 c := &Client{} 216 _, err := c.Get(ts.URL) 217 if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 218 t.Errorf("with default client Get, expected error %q, got %q", e, g) 219 } 220 221 // HEAD request should also have the ability to follow redirects. 222 _, err = c.Head(ts.URL) 223 if e, g := "Head /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 224 t.Errorf("with default client Head, expected error %q, got %q", e, g) 225 } 226 227 // Do should also follow redirects. 228 greq, _ := NewRequest("GET", ts.URL, nil) 229 _, err = c.Do(greq) 230 if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 231 t.Errorf("with default client Do, expected error %q, got %q", e, g) 232 } 233 234 // Requests with an empty Method should also redirect (Issue 12705) 235 greq.Method = "" 236 _, err = c.Do(greq) 237 if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 238 t.Errorf("with default client Do and empty Method, expected error %q, got %q", e, g) 239 } 240 241 var checkErr error 242 var lastVia []*Request 243 c = &Client{CheckRedirect: func(_ *Request, via []*Request) error { 244 lastVia = via 245 return checkErr 246 }} 247 res, err := c.Get(ts.URL) 248 if err != nil { 249 t.Fatalf("Get error: %v", err) 250 } 251 res.Body.Close() 252 finalUrl := res.Request.URL.String() 253 if e, g := "<nil>", fmt.Sprintf("%v", err); e != g { 254 t.Errorf("with custom client, expected error %q, got %q", e, g) 255 } 256 if !strings.HasSuffix(finalUrl, "/?n=15") { 257 t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl) 258 } 259 if e, g := 15, len(lastVia); e != g { 260 t.Errorf("expected lastVia to have contained %d elements; got %d", e, g) 261 } 262 263 checkErr = errors.New("no redirects allowed") 264 res, err = c.Get(ts.URL) 265 if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr { 266 t.Errorf("with redirects forbidden, expected a *url.Error with our 'no redirects allowed' error inside; got %#v (%q)", err, err) 267 } 268 if res == nil { 269 t.Fatalf("Expected a non-nil Response on CheckRedirect failure (https://golang.org/issue/3795)") 270 } 271 res.Body.Close() 272 if res.Header.Get("Location") == "" { 273 t.Errorf("no Location header in Response") 274 } 275 } 276 277 func TestPostRedirects(t *testing.T) { 278 defer afterTest(t) 279 var log struct { 280 sync.Mutex 281 bytes.Buffer 282 } 283 var ts *httptest.Server 284 ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 285 log.Lock() 286 fmt.Fprintf(&log.Buffer, "%s %s ", r.Method, r.RequestURI) 287 log.Unlock() 288 if v := r.URL.Query().Get("code"); v != "" { 289 code, _ := strconv.Atoi(v) 290 if code/100 == 3 { 291 w.Header().Set("Location", ts.URL) 292 } 293 w.WriteHeader(code) 294 } 295 })) 296 defer ts.Close() 297 tests := []struct { 298 suffix string 299 want int // response code 300 }{ 301 {"/", 200}, 302 {"/?code=301", 301}, 303 {"/?code=302", 200}, 304 {"/?code=303", 200}, 305 {"/?code=404", 404}, 306 } 307 for _, tt := range tests { 308 res, err := Post(ts.URL+tt.suffix, "text/plain", strings.NewReader("Some content")) 309 if err != nil { 310 t.Fatal(err) 311 } 312 if res.StatusCode != tt.want { 313 t.Errorf("POST %s: status code = %d; want %d", tt.suffix, res.StatusCode, tt.want) 314 } 315 } 316 log.Lock() 317 got := log.String() 318 log.Unlock() 319 want := "POST / POST /?code=301 POST /?code=302 GET / POST /?code=303 GET / POST /?code=404 " 320 if got != want { 321 t.Errorf("Log differs.\n Got: %q\nWant: %q", got, want) 322 } 323 } 324 325 var expectedCookies = []*Cookie{ 326 {Name: "ChocolateChip", Value: "tasty"}, 327 {Name: "First", Value: "Hit"}, 328 {Name: "Second", Value: "Hit"}, 329 } 330 331 var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 332 for _, cookie := range r.Cookies() { 333 SetCookie(w, cookie) 334 } 335 if r.URL.Path == "/" { 336 SetCookie(w, expectedCookies[1]) 337 Redirect(w, r, "/second", StatusMovedPermanently) 338 } else { 339 SetCookie(w, expectedCookies[2]) 340 w.Write([]byte("hello")) 341 } 342 }) 343 344 func TestClientSendsCookieFromJar(t *testing.T) { 345 defer afterTest(t) 346 tr := &recordingTransport{} 347 client := &Client{Transport: tr} 348 client.Jar = &TestJar{perURL: make(map[string][]*Cookie)} 349 us := "http://dummy.faketld/" 350 u, _ := url.Parse(us) 351 client.Jar.SetCookies(u, expectedCookies) 352 353 client.Get(us) // Note: doesn't hit network 354 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 355 356 client.Head(us) // Note: doesn't hit network 357 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 358 359 client.Post(us, "text/plain", strings.NewReader("body")) // Note: doesn't hit network 360 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 361 362 client.PostForm(us, url.Values{}) // Note: doesn't hit network 363 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 364 365 req, _ := NewRequest("GET", us, nil) 366 client.Do(req) // Note: doesn't hit network 367 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 368 369 req, _ = NewRequest("POST", us, nil) 370 client.Do(req) // Note: doesn't hit network 371 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 372 } 373 374 // Just enough correctness for our redirect tests. Uses the URL.Host as the 375 // scope of all cookies. 376 type TestJar struct { 377 m sync.Mutex 378 perURL map[string][]*Cookie 379 } 380 381 func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) { 382 j.m.Lock() 383 defer j.m.Unlock() 384 if j.perURL == nil { 385 j.perURL = make(map[string][]*Cookie) 386 } 387 j.perURL[u.Host] = cookies 388 } 389 390 func (j *TestJar) Cookies(u *url.URL) []*Cookie { 391 j.m.Lock() 392 defer j.m.Unlock() 393 return j.perURL[u.Host] 394 } 395 396 func TestRedirectCookiesJar(t *testing.T) { 397 defer afterTest(t) 398 var ts *httptest.Server 399 ts = httptest.NewServer(echoCookiesRedirectHandler) 400 defer ts.Close() 401 c := &Client{ 402 Jar: new(TestJar), 403 } 404 u, _ := url.Parse(ts.URL) 405 c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]}) 406 resp, err := c.Get(ts.URL) 407 if err != nil { 408 t.Fatalf("Get: %v", err) 409 } 410 resp.Body.Close() 411 matchReturnedCookies(t, expectedCookies, resp.Cookies()) 412 } 413 414 func matchReturnedCookies(t *testing.T, expected, given []*Cookie) { 415 if len(given) != len(expected) { 416 t.Logf("Received cookies: %v", given) 417 t.Errorf("Expected %d cookies, got %d", len(expected), len(given)) 418 } 419 for _, ec := range expected { 420 foundC := false 421 for _, c := range given { 422 if ec.Name == c.Name && ec.Value == c.Value { 423 foundC = true 424 break 425 } 426 } 427 if !foundC { 428 t.Errorf("Missing cookie %v", ec) 429 } 430 } 431 } 432 433 func TestJarCalls(t *testing.T) { 434 defer afterTest(t) 435 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 436 pathSuffix := r.RequestURI[1:] 437 if r.RequestURI == "/nosetcookie" { 438 return // don't set cookies for this path 439 } 440 SetCookie(w, &Cookie{Name: "name" + pathSuffix, Value: "val" + pathSuffix}) 441 if r.RequestURI == "/" { 442 Redirect(w, r, "http://secondhost.fake/secondpath", 302) 443 } 444 })) 445 defer ts.Close() 446 jar := new(RecordingJar) 447 c := &Client{ 448 Jar: jar, 449 Transport: &Transport{ 450 Dial: func(_ string, _ string) (net.Conn, error) { 451 return net.Dial("tcp", ts.Listener.Addr().String()) 452 }, 453 }, 454 } 455 _, err := c.Get("http://firsthost.fake/") 456 if err != nil { 457 t.Fatal(err) 458 } 459 _, err = c.Get("http://firsthost.fake/nosetcookie") 460 if err != nil { 461 t.Fatal(err) 462 } 463 got := jar.log.String() 464 want := `Cookies("http://firsthost.fake/") 465 SetCookie("http://firsthost.fake/", [name=val]) 466 Cookies("http://secondhost.fake/secondpath") 467 SetCookie("http://secondhost.fake/secondpath", [namesecondpath=valsecondpath]) 468 Cookies("http://firsthost.fake/nosetcookie") 469 ` 470 if got != want { 471 t.Errorf("Got Jar calls:\n%s\nWant:\n%s", got, want) 472 } 473 } 474 475 // RecordingJar keeps a log of calls made to it, without 476 // tracking any cookies. 477 type RecordingJar struct { 478 mu sync.Mutex 479 log bytes.Buffer 480 } 481 482 func (j *RecordingJar) SetCookies(u *url.URL, cookies []*Cookie) { 483 j.logf("SetCookie(%q, %v)\n", u, cookies) 484 } 485 486 func (j *RecordingJar) Cookies(u *url.URL) []*Cookie { 487 j.logf("Cookies(%q)\n", u) 488 return nil 489 } 490 491 func (j *RecordingJar) logf(format string, args ...interface{}) { 492 j.mu.Lock() 493 defer j.mu.Unlock() 494 fmt.Fprintf(&j.log, format, args...) 495 } 496 497 func TestStreamingGet_h1(t *testing.T) { testStreamingGet(t, h1Mode) } 498 func TestStreamingGet_h2(t *testing.T) { testStreamingGet(t, h2Mode) } 499 500 func testStreamingGet(t *testing.T, h2 bool) { 501 defer afterTest(t) 502 say := make(chan string) 503 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 504 w.(Flusher).Flush() 505 for str := range say { 506 w.Write([]byte(str)) 507 w.(Flusher).Flush() 508 } 509 })) 510 defer cst.close() 511 512 c := cst.c 513 res, err := c.Get(cst.ts.URL) 514 if err != nil { 515 t.Fatal(err) 516 } 517 var buf [10]byte 518 for _, str := range []string{"i", "am", "also", "known", "as", "comet"} { 519 say <- str 520 n, err := io.ReadFull(res.Body, buf[0:len(str)]) 521 if err != nil { 522 t.Fatalf("ReadFull on %q: %v", str, err) 523 } 524 if n != len(str) { 525 t.Fatalf("Receiving %q, only read %d bytes", str, n) 526 } 527 got := string(buf[0:n]) 528 if got != str { 529 t.Fatalf("Expected %q, got %q", str, got) 530 } 531 } 532 close(say) 533 _, err = io.ReadFull(res.Body, buf[0:1]) 534 if err != io.EOF { 535 t.Fatalf("at end expected EOF, got %v", err) 536 } 537 } 538 539 type writeCountingConn struct { 540 net.Conn 541 count *int 542 } 543 544 func (c *writeCountingConn) Write(p []byte) (int, error) { 545 *c.count++ 546 return c.Conn.Write(p) 547 } 548 549 // TestClientWrites verifies that client requests are buffered and we 550 // don't send a TCP packet per line of the http request + body. 551 func TestClientWrites(t *testing.T) { 552 defer afterTest(t) 553 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 554 })) 555 defer ts.Close() 556 557 writes := 0 558 dialer := func(netz string, addr string) (net.Conn, error) { 559 c, err := net.Dial(netz, addr) 560 if err == nil { 561 c = &writeCountingConn{c, &writes} 562 } 563 return c, err 564 } 565 c := &Client{Transport: &Transport{Dial: dialer}} 566 567 _, err := c.Get(ts.URL) 568 if err != nil { 569 t.Fatal(err) 570 } 571 if writes != 1 { 572 t.Errorf("Get request did %d Write calls, want 1", writes) 573 } 574 575 writes = 0 576 _, err = c.PostForm(ts.URL, url.Values{"foo": {"bar"}}) 577 if err != nil { 578 t.Fatal(err) 579 } 580 if writes != 1 { 581 t.Errorf("Post request did %d Write calls, want 1", writes) 582 } 583 } 584 585 func TestClientInsecureTransport(t *testing.T) { 586 defer afterTest(t) 587 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 588 w.Write([]byte("Hello")) 589 })) 590 errc := make(chanWriter, 10) // but only expecting 1 591 ts.Config.ErrorLog = log.New(errc, "", 0) 592 defer ts.Close() 593 594 // TODO(bradfitz): add tests for skipping hostname checks too? 595 // would require a new cert for testing, and probably 596 // redundant with these tests. 597 for _, insecure := range []bool{true, false} { 598 tr := &Transport{ 599 TLSClientConfig: &tls.Config{ 600 InsecureSkipVerify: insecure, 601 }, 602 } 603 defer tr.CloseIdleConnections() 604 c := &Client{Transport: tr} 605 res, err := c.Get(ts.URL) 606 if (err == nil) != insecure { 607 t.Errorf("insecure=%v: got unexpected err=%v", insecure, err) 608 } 609 if res != nil { 610 res.Body.Close() 611 } 612 } 613 614 select { 615 case v := <-errc: 616 if !strings.Contains(v, "TLS handshake error") { 617 t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v) 618 } 619 case <-time.After(5 * time.Second): 620 t.Errorf("timeout waiting for logged error") 621 } 622 623 } 624 625 func TestClientErrorWithRequestURI(t *testing.T) { 626 defer afterTest(t) 627 req, _ := NewRequest("GET", "http://localhost:1234/", nil) 628 req.RequestURI = "/this/field/is/illegal/and/should/error/" 629 _, err := DefaultClient.Do(req) 630 if err == nil { 631 t.Fatalf("expected an error") 632 } 633 if !strings.Contains(err.Error(), "RequestURI") { 634 t.Errorf("wanted error mentioning RequestURI; got error: %v", err) 635 } 636 } 637 638 func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport { 639 certs := x509.NewCertPool() 640 for _, c := range ts.TLS.Certificates { 641 roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1]) 642 if err != nil { 643 t.Fatalf("error parsing server's root cert: %v", err) 644 } 645 for _, root := range roots { 646 certs.AddCert(root) 647 } 648 } 649 return &Transport{ 650 TLSClientConfig: &tls.Config{RootCAs: certs}, 651 } 652 } 653 654 func TestClientWithCorrectTLSServerName(t *testing.T) { 655 defer afterTest(t) 656 657 const serverName = "example.com" 658 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 659 if r.TLS.ServerName != serverName { 660 t.Errorf("expected client to set ServerName %q, got: %q", serverName, r.TLS.ServerName) 661 } 662 })) 663 defer ts.Close() 664 665 trans := newTLSTransport(t, ts) 666 trans.TLSClientConfig.ServerName = serverName 667 c := &Client{Transport: trans} 668 if _, err := c.Get(ts.URL); err != nil { 669 t.Fatalf("expected successful TLS connection, got error: %v", err) 670 } 671 } 672 673 func TestClientWithIncorrectTLSServerName(t *testing.T) { 674 defer afterTest(t) 675 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 676 defer ts.Close() 677 errc := make(chanWriter, 10) // but only expecting 1 678 ts.Config.ErrorLog = log.New(errc, "", 0) 679 680 trans := newTLSTransport(t, ts) 681 trans.TLSClientConfig.ServerName = "badserver" 682 c := &Client{Transport: trans} 683 _, err := c.Get(ts.URL) 684 if err == nil { 685 t.Fatalf("expected an error") 686 } 687 if !strings.Contains(err.Error(), "127.0.0.1") || !strings.Contains(err.Error(), "badserver") { 688 t.Errorf("wanted error mentioning 127.0.0.1 and badserver; got error: %v", err) 689 } 690 select { 691 case v := <-errc: 692 if !strings.Contains(v, "TLS handshake error") { 693 t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v) 694 } 695 case <-time.After(5 * time.Second): 696 t.Errorf("timeout waiting for logged error") 697 } 698 } 699 700 // Test for golang.org/issue/5829; the Transport should respect TLSClientConfig.ServerName 701 // when not empty. 702 // 703 // tls.Config.ServerName (non-empty, set to "example.com") takes 704 // precedence over "some-other-host.tld" which previously incorrectly 705 // took precedence. We don't actually connect to (or even resolve) 706 // "some-other-host.tld", though, because of the Transport.Dial hook. 707 // 708 // The httptest.Server has a cert with "example.com" as its name. 709 func TestTransportUsesTLSConfigServerName(t *testing.T) { 710 defer afterTest(t) 711 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 712 w.Write([]byte("Hello")) 713 })) 714 defer ts.Close() 715 716 tr := newTLSTransport(t, ts) 717 tr.TLSClientConfig.ServerName = "example.com" // one of httptest's Server cert names 718 tr.Dial = func(netw, addr string) (net.Conn, error) { 719 return net.Dial(netw, ts.Listener.Addr().String()) 720 } 721 defer tr.CloseIdleConnections() 722 c := &Client{Transport: tr} 723 res, err := c.Get("https://some-other-host.tld/") 724 if err != nil { 725 t.Fatal(err) 726 } 727 res.Body.Close() 728 } 729 730 func TestResponseSetsTLSConnectionState(t *testing.T) { 731 defer afterTest(t) 732 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 733 w.Write([]byte("Hello")) 734 })) 735 defer ts.Close() 736 737 tr := newTLSTransport(t, ts) 738 tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} 739 tr.Dial = func(netw, addr string) (net.Conn, error) { 740 return net.Dial(netw, ts.Listener.Addr().String()) 741 } 742 defer tr.CloseIdleConnections() 743 c := &Client{Transport: tr} 744 res, err := c.Get("https://example.com/") 745 if err != nil { 746 t.Fatal(err) 747 } 748 defer res.Body.Close() 749 if res.TLS == nil { 750 t.Fatal("Response didn't set TLS Connection State.") 751 } 752 if got, want := res.TLS.CipherSuite, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA; got != want { 753 t.Errorf("TLS Cipher Suite = %d; want %d", got, want) 754 } 755 } 756 757 // Check that an HTTPS client can interpret a particular TLS error 758 // to determine that the server is speaking HTTP. 759 // See golang.org/issue/11111. 760 func TestHTTPSClientDetectsHTTPServer(t *testing.T) { 761 defer afterTest(t) 762 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 763 defer ts.Close() 764 765 _, err := Get(strings.Replace(ts.URL, "http", "https", 1)) 766 if got := err.Error(); !strings.Contains(got, "HTTP response to HTTPS client") { 767 t.Fatalf("error = %q; want error indicating HTTP response to HTTPS request", got) 768 } 769 } 770 771 // Verify Response.ContentLength is populated. https://golang.org/issue/4126 772 func TestClientHeadContentLength_h1(t *testing.T) { 773 testClientHeadContentLength(t, h1Mode) 774 } 775 776 func TestClientHeadContentLength_h2(t *testing.T) { 777 testClientHeadContentLength(t, h2Mode) 778 } 779 780 func testClientHeadContentLength(t *testing.T, h2 bool) { 781 defer afterTest(t) 782 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 783 if v := r.FormValue("cl"); v != "" { 784 w.Header().Set("Content-Length", v) 785 } 786 })) 787 defer cst.close() 788 tests := []struct { 789 suffix string 790 want int64 791 }{ 792 {"/?cl=1234", 1234}, 793 {"/?cl=0", 0}, 794 {"", -1}, 795 } 796 for _, tt := range tests { 797 req, _ := NewRequest("HEAD", cst.ts.URL+tt.suffix, nil) 798 res, err := cst.c.Do(req) 799 if err != nil { 800 t.Fatal(err) 801 } 802 if res.ContentLength != tt.want { 803 t.Errorf("Content-Length = %d; want %d", res.ContentLength, tt.want) 804 } 805 bs, err := ioutil.ReadAll(res.Body) 806 if err != nil { 807 t.Fatal(err) 808 } 809 if len(bs) != 0 { 810 t.Errorf("Unexpected content: %q", bs) 811 } 812 } 813 } 814 815 func TestEmptyPasswordAuth(t *testing.T) { 816 defer afterTest(t) 817 gopher := "gopher" 818 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 819 auth := r.Header.Get("Authorization") 820 if strings.HasPrefix(auth, "Basic ") { 821 encoded := auth[6:] 822 decoded, err := base64.StdEncoding.DecodeString(encoded) 823 if err != nil { 824 t.Fatal(err) 825 } 826 expected := gopher + ":" 827 s := string(decoded) 828 if expected != s { 829 t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected) 830 } 831 } else { 832 t.Errorf("Invalid auth %q", auth) 833 } 834 })) 835 defer ts.Close() 836 c := &Client{} 837 req, err := NewRequest("GET", ts.URL, nil) 838 if err != nil { 839 t.Fatal(err) 840 } 841 req.URL.User = url.User(gopher) 842 resp, err := c.Do(req) 843 if err != nil { 844 t.Fatal(err) 845 } 846 defer resp.Body.Close() 847 } 848 849 func TestBasicAuth(t *testing.T) { 850 defer afterTest(t) 851 tr := &recordingTransport{} 852 client := &Client{Transport: tr} 853 854 url := "http://My%20User:My%20Pass@dummy.faketld/" 855 expected := "My User:My Pass" 856 client.Get(url) 857 858 if tr.req.Method != "GET" { 859 t.Errorf("got method %q, want %q", tr.req.Method, "GET") 860 } 861 if tr.req.URL.String() != url { 862 t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) 863 } 864 if tr.req.Header == nil { 865 t.Fatalf("expected non-nil request Header") 866 } 867 auth := tr.req.Header.Get("Authorization") 868 if strings.HasPrefix(auth, "Basic ") { 869 encoded := auth[6:] 870 decoded, err := base64.StdEncoding.DecodeString(encoded) 871 if err != nil { 872 t.Fatal(err) 873 } 874 s := string(decoded) 875 if expected != s { 876 t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected) 877 } 878 } else { 879 t.Errorf("Invalid auth %q", auth) 880 } 881 } 882 883 func TestBasicAuthHeadersPreserved(t *testing.T) { 884 defer afterTest(t) 885 tr := &recordingTransport{} 886 client := &Client{Transport: tr} 887 888 // If Authorization header is provided, username in URL should not override it 889 url := "http://My%20User@dummy.faketld/" 890 req, err := NewRequest("GET", url, nil) 891 if err != nil { 892 t.Fatal(err) 893 } 894 req.SetBasicAuth("My User", "My Pass") 895 expected := "My User:My Pass" 896 client.Do(req) 897 898 if tr.req.Method != "GET" { 899 t.Errorf("got method %q, want %q", tr.req.Method, "GET") 900 } 901 if tr.req.URL.String() != url { 902 t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) 903 } 904 if tr.req.Header == nil { 905 t.Fatalf("expected non-nil request Header") 906 } 907 auth := tr.req.Header.Get("Authorization") 908 if strings.HasPrefix(auth, "Basic ") { 909 encoded := auth[6:] 910 decoded, err := base64.StdEncoding.DecodeString(encoded) 911 if err != nil { 912 t.Fatal(err) 913 } 914 s := string(decoded) 915 if expected != s { 916 t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected) 917 } 918 } else { 919 t.Errorf("Invalid auth %q", auth) 920 } 921 922 } 923 924 func TestClientTimeout_h1(t *testing.T) { testClientTimeout(t, h1Mode) } 925 func TestClientTimeout_h2(t *testing.T) { 926 t.Skip("skipping in http2 mode; golang.org/issue/13540") 927 testClientTimeout(t, h2Mode) 928 } 929 930 func testClientTimeout(t *testing.T, h2 bool) { 931 if testing.Short() { 932 t.Skip("skipping in short mode") 933 } 934 defer afterTest(t) 935 sawRoot := make(chan bool, 1) 936 sawSlow := make(chan bool, 1) 937 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 938 if r.URL.Path == "/" { 939 sawRoot <- true 940 Redirect(w, r, "/slow", StatusFound) 941 return 942 } 943 if r.URL.Path == "/slow" { 944 w.Write([]byte("Hello")) 945 w.(Flusher).Flush() 946 sawSlow <- true 947 time.Sleep(2 * time.Second) 948 return 949 } 950 })) 951 defer cst.close() 952 const timeout = 500 * time.Millisecond 953 cst.c.Timeout = timeout 954 955 res, err := cst.c.Get(cst.ts.URL) 956 if err != nil { 957 t.Fatal(err) 958 } 959 960 select { 961 case <-sawRoot: 962 // good. 963 default: 964 t.Fatal("handler never got / request") 965 } 966 967 select { 968 case <-sawSlow: 969 // good. 970 default: 971 t.Fatal("handler never got /slow request") 972 } 973 974 errc := make(chan error, 1) 975 go func() { 976 _, err := ioutil.ReadAll(res.Body) 977 errc <- err 978 res.Body.Close() 979 }() 980 981 const failTime = timeout * 2 982 select { 983 case err := <-errc: 984 if err == nil { 985 t.Fatal("expected error from ReadAll") 986 } 987 ne, ok := err.(net.Error) 988 if !ok { 989 t.Errorf("error value from ReadAll was %T; expected some net.Error", err) 990 } else if !ne.Timeout() { 991 t.Errorf("net.Error.Timeout = false; want true") 992 } 993 if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") { 994 t.Errorf("error string = %q; missing timeout substring", got) 995 } 996 case <-time.After(failTime): 997 t.Errorf("timeout after %v waiting for timeout of %v", failTime, timeout) 998 } 999 } 1000 1001 func TestClientTimeout_Headers_h1(t *testing.T) { testClientTimeout_Headers(t, h1Mode) } 1002 func TestClientTimeout_Headers_h2(t *testing.T) { 1003 t.Skip("skipping in http2 mode; golang.org/issue/13540") 1004 testClientTimeout_Headers(t, h2Mode) 1005 } 1006 1007 // Client.Timeout firing before getting to the body 1008 func testClientTimeout_Headers(t *testing.T, h2 bool) { 1009 if testing.Short() { 1010 t.Skip("skipping in short mode") 1011 } 1012 defer afterTest(t) 1013 donec := make(chan bool) 1014 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1015 <-donec 1016 })) 1017 defer cst.close() 1018 // Note that we use a channel send here and not a close. 1019 // The race detector doesn't know that we're waiting for a timeout 1020 // and thinks that the waitgroup inside httptest.Server is added to concurrently 1021 // with us closing it. If we timed out immediately, we could close the testserver 1022 // before we entered the handler. We're not timing out immediately and there's 1023 // no way we would be done before we entered the handler, but the race detector 1024 // doesn't know this, so synchronize explicitly. 1025 defer func() { donec <- true }() 1026 1027 cst.c.Timeout = 500 * time.Millisecond 1028 _, err := cst.c.Get(cst.ts.URL) 1029 if err == nil { 1030 t.Fatal("got response from Get; expected error") 1031 } 1032 if _, ok := err.(*url.Error); !ok { 1033 t.Fatalf("Got error of type %T; want *url.Error", err) 1034 } 1035 ne, ok := err.(net.Error) 1036 if !ok { 1037 t.Fatalf("Got error of type %T; want some net.Error", err) 1038 } 1039 if !ne.Timeout() { 1040 t.Error("net.Error.Timeout = false; want true") 1041 } 1042 if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") { 1043 t.Errorf("error string = %q; missing timeout substring", got) 1044 } 1045 } 1046 1047 func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) } 1048 func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) } 1049 func testClientRedirectEatsBody(t *testing.T, h2 bool) { 1050 defer afterTest(t) 1051 saw := make(chan string, 2) 1052 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1053 saw <- r.RemoteAddr 1054 if r.URL.Path == "/" { 1055 Redirect(w, r, "/foo", StatusFound) // which includes a body 1056 } 1057 })) 1058 defer cst.close() 1059 1060 res, err := cst.c.Get(cst.ts.URL) 1061 if err != nil { 1062 t.Fatal(err) 1063 } 1064 _, err = ioutil.ReadAll(res.Body) 1065 if err != nil { 1066 t.Fatal(err) 1067 } 1068 res.Body.Close() 1069 1070 var first string 1071 select { 1072 case first = <-saw: 1073 default: 1074 t.Fatal("server didn't see a request") 1075 } 1076 1077 var second string 1078 select { 1079 case second = <-saw: 1080 default: 1081 t.Fatal("server didn't see a second request") 1082 } 1083 1084 if first != second { 1085 t.Fatal("server saw different client ports before & after the redirect") 1086 } 1087 } 1088 1089 // eofReaderFunc is an io.Reader that runs itself, and then returns io.EOF. 1090 type eofReaderFunc func() 1091 1092 func (f eofReaderFunc) Read(p []byte) (n int, err error) { 1093 f() 1094 return 0, io.EOF 1095 } 1096 1097 func TestReferer(t *testing.T) { 1098 tests := []struct { 1099 lastReq, newReq string // from -> to URLs 1100 want string 1101 }{ 1102 // don't send user: 1103 {"http://gopher@test.com", "http://link.com", "http://test.com"}, 1104 {"https://gopher@test.com", "https://link.com", "https://test.com"}, 1105 1106 // don't send a user and password: 1107 {"http://gopher:go@test.com", "http://link.com", "http://test.com"}, 1108 {"https://gopher:go@test.com", "https://link.com", "https://test.com"}, 1109 1110 // nothing to do: 1111 {"http://test.com", "http://link.com", "http://test.com"}, 1112 {"https://test.com", "https://link.com", "https://test.com"}, 1113 1114 // https to http doesn't send a referer: 1115 {"https://test.com", "http://link.com", ""}, 1116 {"https://gopher:go@test.com", "http://link.com", ""}, 1117 } 1118 for _, tt := range tests { 1119 l, err := url.Parse(tt.lastReq) 1120 if err != nil { 1121 t.Fatal(err) 1122 } 1123 n, err := url.Parse(tt.newReq) 1124 if err != nil { 1125 t.Fatal(err) 1126 } 1127 r := ExportRefererForURL(l, n) 1128 if r != tt.want { 1129 t.Errorf("refererForURL(%q, %q) = %q; want %q", tt.lastReq, tt.newReq, r, tt.want) 1130 } 1131 } 1132 }