github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/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 "context" 12 "crypto/tls" 13 "crypto/x509" 14 "encoding/base64" 15 "errors" 16 "fmt" 17 "io" 18 "io/ioutil" 19 "log" 20 "net" 21 . "net/http" 22 "net/http/cookiejar" 23 "net/http/httptest" 24 "net/url" 25 "reflect" 26 "strconv" 27 "strings" 28 "sync" 29 "sync/atomic" 30 "testing" 31 "time" 32 ) 33 34 var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 35 w.Header().Set("Last-Modified", "sometime") 36 fmt.Fprintf(w, "User-agent: go\nDisallow: /something/") 37 }) 38 39 // pedanticReadAll works like ioutil.ReadAll but additionally 40 // verifies that r obeys the documented io.Reader contract. 41 func pedanticReadAll(r io.Reader) (b []byte, err error) { 42 var bufa [64]byte 43 buf := bufa[:] 44 for { 45 n, err := r.Read(buf) 46 if n == 0 && err == nil { 47 return nil, fmt.Errorf("Read: n=0 with err=nil") 48 } 49 b = append(b, buf[:n]...) 50 if err == io.EOF { 51 n, err := r.Read(buf) 52 if n != 0 || err != io.EOF { 53 return nil, fmt.Errorf("Read: n=%d err=%#v after EOF", n, err) 54 } 55 return b, nil 56 } 57 if err != nil { 58 return b, err 59 } 60 } 61 } 62 63 type chanWriter chan string 64 65 func (w chanWriter) Write(p []byte) (n int, err error) { 66 w <- string(p) 67 return len(p), nil 68 } 69 70 func TestClient(t *testing.T) { 71 setParallel(t) 72 defer afterTest(t) 73 ts := httptest.NewServer(robotsTxtHandler) 74 defer ts.Close() 75 76 c := &Client{Transport: &Transport{DisableKeepAlives: true}} 77 r, err := c.Get(ts.URL) 78 var b []byte 79 if err == nil { 80 b, err = pedanticReadAll(r.Body) 81 r.Body.Close() 82 } 83 if err != nil { 84 t.Error(err) 85 } else if s := string(b); !strings.HasPrefix(s, "User-agent:") { 86 t.Errorf("Incorrect page body (did not begin with User-agent): %q", s) 87 } 88 } 89 90 func TestClientHead_h1(t *testing.T) { testClientHead(t, h1Mode) } 91 func TestClientHead_h2(t *testing.T) { testClientHead(t, h2Mode) } 92 93 func testClientHead(t *testing.T, h2 bool) { 94 defer afterTest(t) 95 cst := newClientServerTest(t, h2, robotsTxtHandler) 96 defer cst.close() 97 98 r, err := cst.c.Head(cst.ts.URL) 99 if err != nil { 100 t.Fatal(err) 101 } 102 if _, ok := r.Header["Last-Modified"]; !ok { 103 t.Error("Last-Modified header not found.") 104 } 105 } 106 107 type recordingTransport struct { 108 req *Request 109 } 110 111 func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error) { 112 t.req = req 113 return nil, errors.New("dummy impl") 114 } 115 116 func TestGetRequestFormat(t *testing.T) { 117 setParallel(t) 118 defer afterTest(t) 119 tr := &recordingTransport{} 120 client := &Client{Transport: tr} 121 url := "http://dummy.faketld/" 122 client.Get(url) // Note: doesn't hit network 123 if tr.req.Method != "GET" { 124 t.Errorf("expected method %q; got %q", "GET", tr.req.Method) 125 } 126 if tr.req.URL.String() != url { 127 t.Errorf("expected URL %q; got %q", url, tr.req.URL.String()) 128 } 129 if tr.req.Header == nil { 130 t.Errorf("expected non-nil request Header") 131 } 132 } 133 134 func TestPostRequestFormat(t *testing.T) { 135 defer afterTest(t) 136 tr := &recordingTransport{} 137 client := &Client{Transport: tr} 138 139 url := "http://dummy.faketld/" 140 json := `{"key":"value"}` 141 b := strings.NewReader(json) 142 client.Post(url, "application/json", b) // Note: doesn't hit network 143 144 if tr.req.Method != "POST" { 145 t.Errorf("got method %q, want %q", tr.req.Method, "POST") 146 } 147 if tr.req.URL.String() != url { 148 t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) 149 } 150 if tr.req.Header == nil { 151 t.Fatalf("expected non-nil request Header") 152 } 153 if tr.req.Close { 154 t.Error("got Close true, want false") 155 } 156 if g, e := tr.req.ContentLength, int64(len(json)); g != e { 157 t.Errorf("got ContentLength %d, want %d", g, e) 158 } 159 } 160 161 func TestPostFormRequestFormat(t *testing.T) { 162 defer afterTest(t) 163 tr := &recordingTransport{} 164 client := &Client{Transport: tr} 165 166 urlStr := "http://dummy.faketld/" 167 form := make(url.Values) 168 form.Set("foo", "bar") 169 form.Add("foo", "bar2") 170 form.Set("bar", "baz") 171 client.PostForm(urlStr, form) // Note: doesn't hit network 172 173 if tr.req.Method != "POST" { 174 t.Errorf("got method %q, want %q", tr.req.Method, "POST") 175 } 176 if tr.req.URL.String() != urlStr { 177 t.Errorf("got URL %q, want %q", tr.req.URL.String(), urlStr) 178 } 179 if tr.req.Header == nil { 180 t.Fatalf("expected non-nil request Header") 181 } 182 if g, e := tr.req.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; g != e { 183 t.Errorf("got Content-Type %q, want %q", g, e) 184 } 185 if tr.req.Close { 186 t.Error("got Close true, want false") 187 } 188 // Depending on map iteration, body can be either of these. 189 expectedBody := "foo=bar&foo=bar2&bar=baz" 190 expectedBody1 := "bar=baz&foo=bar&foo=bar2" 191 if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e { 192 t.Errorf("got ContentLength %d, want %d", g, e) 193 } 194 bodyb, err := ioutil.ReadAll(tr.req.Body) 195 if err != nil { 196 t.Fatalf("ReadAll on req.Body: %v", err) 197 } 198 if g := string(bodyb); g != expectedBody && g != expectedBody1 { 199 t.Errorf("got body %q, want %q or %q", g, expectedBody, expectedBody1) 200 } 201 } 202 203 func TestClientRedirects(t *testing.T) { 204 setParallel(t) 205 defer afterTest(t) 206 var ts *httptest.Server 207 ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 208 n, _ := strconv.Atoi(r.FormValue("n")) 209 // Test Referer header. (7 is arbitrary position to test at) 210 if n == 7 { 211 if g, e := r.Referer(), ts.URL+"/?n=6"; e != g { 212 t.Errorf("on request ?n=7, expected referer of %q; got %q", e, g) 213 } 214 } 215 if n < 15 { 216 Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusTemporaryRedirect) 217 return 218 } 219 fmt.Fprintf(w, "n=%d", n) 220 })) 221 defer ts.Close() 222 223 tr := &Transport{} 224 defer tr.CloseIdleConnections() 225 226 c := &Client{Transport: tr} 227 _, err := c.Get(ts.URL) 228 if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 229 t.Errorf("with default client Get, expected error %q, got %q", e, g) 230 } 231 232 // HEAD request should also have the ability to follow redirects. 233 _, err = c.Head(ts.URL) 234 if e, g := "Head /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 235 t.Errorf("with default client Head, expected error %q, got %q", e, g) 236 } 237 238 // Do should also follow redirects. 239 greq, _ := NewRequest("GET", ts.URL, nil) 240 _, err = c.Do(greq) 241 if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 242 t.Errorf("with default client Do, expected error %q, got %q", e, g) 243 } 244 245 // Requests with an empty Method should also redirect (Issue 12705) 246 greq.Method = "" 247 _, err = c.Do(greq) 248 if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { 249 t.Errorf("with default client Do and empty Method, expected error %q, got %q", e, g) 250 } 251 252 var checkErr error 253 var lastVia []*Request 254 var lastReq *Request 255 c = &Client{ 256 Transport: tr, 257 CheckRedirect: func(req *Request, via []*Request) error { 258 lastReq = req 259 lastVia = via 260 return checkErr 261 }, 262 } 263 res, err := c.Get(ts.URL) 264 if err != nil { 265 t.Fatalf("Get error: %v", err) 266 } 267 res.Body.Close() 268 finalUrl := res.Request.URL.String() 269 if e, g := "<nil>", fmt.Sprintf("%v", err); e != g { 270 t.Errorf("with custom client, expected error %q, got %q", e, g) 271 } 272 if !strings.HasSuffix(finalUrl, "/?n=15") { 273 t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl) 274 } 275 if e, g := 15, len(lastVia); e != g { 276 t.Errorf("expected lastVia to have contained %d elements; got %d", e, g) 277 } 278 279 // Test that Request.Cancel is propagated between requests (Issue 14053) 280 creq, _ := NewRequest("HEAD", ts.URL, nil) 281 cancel := make(chan struct{}) 282 creq.Cancel = cancel 283 if _, err := c.Do(creq); err != nil { 284 t.Fatal(err) 285 } 286 if lastReq == nil { 287 t.Fatal("didn't see redirect") 288 } 289 if lastReq.Cancel != cancel { 290 t.Errorf("expected lastReq to have the cancel channel set on the initial req") 291 } 292 293 checkErr = errors.New("no redirects allowed") 294 res, err = c.Get(ts.URL) 295 if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr { 296 t.Errorf("with redirects forbidden, expected a *url.Error with our 'no redirects allowed' error inside; got %#v (%q)", err, err) 297 } 298 if res == nil { 299 t.Fatalf("Expected a non-nil Response on CheckRedirect failure (https://golang.org/issue/3795)") 300 } 301 res.Body.Close() 302 if res.Header.Get("Location") == "" { 303 t.Errorf("no Location header in Response") 304 } 305 } 306 307 func TestClientRedirectContext(t *testing.T) { 308 setParallel(t) 309 defer afterTest(t) 310 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 311 Redirect(w, r, "/", StatusTemporaryRedirect) 312 })) 313 defer ts.Close() 314 315 tr := &Transport{} 316 defer tr.CloseIdleConnections() 317 318 ctx, cancel := context.WithCancel(context.Background()) 319 c := &Client{ 320 Transport: tr, 321 CheckRedirect: func(req *Request, via []*Request) error { 322 cancel() 323 if len(via) > 2 { 324 return errors.New("too many redirects") 325 } 326 return nil 327 }, 328 } 329 req, _ := NewRequest("GET", ts.URL, nil) 330 req = req.WithContext(ctx) 331 _, err := c.Do(req) 332 ue, ok := err.(*url.Error) 333 if !ok { 334 t.Fatalf("got error %T; want *url.Error", err) 335 } 336 if ue.Err != context.Canceled { 337 t.Errorf("url.Error.Err = %v; want %v", ue.Err, context.Canceled) 338 } 339 } 340 341 type redirectTest struct { 342 suffix string 343 want int // response code 344 redirectBody string 345 } 346 347 func TestPostRedirects(t *testing.T) { 348 postRedirectTests := []redirectTest{ 349 {"/", 200, "first"}, 350 {"/?code=301&next=302", 200, "c301"}, 351 {"/?code=302&next=302", 200, "c302"}, 352 {"/?code=303&next=301", 200, "c303wc301"}, // Issue 9348 353 {"/?code=304", 304, "c304"}, 354 {"/?code=305", 305, "c305"}, 355 {"/?code=307&next=303,308,302", 200, "c307"}, 356 {"/?code=308&next=302,301", 200, "c308"}, 357 {"/?code=404", 404, "c404"}, 358 } 359 360 wantSegments := []string{ 361 `POST / "first"`, 362 `POST /?code=301&next=302 "c301"`, 363 `GET /?code=302 ""`, 364 `GET / ""`, 365 `POST /?code=302&next=302 "c302"`, 366 `GET /?code=302 ""`, 367 `GET / ""`, 368 `POST /?code=303&next=301 "c303wc301"`, 369 `GET /?code=301 ""`, 370 `GET / ""`, 371 `POST /?code=304 "c304"`, 372 `POST /?code=305 "c305"`, 373 `POST /?code=307&next=303,308,302 "c307"`, 374 `POST /?code=303&next=308,302 "c307"`, 375 `GET /?code=308&next=302 ""`, 376 `GET /?code=302 "c307"`, 377 `GET / ""`, 378 `POST /?code=308&next=302,301 "c308"`, 379 `POST /?code=302&next=301 "c308"`, 380 `GET /?code=301 ""`, 381 `GET / ""`, 382 `POST /?code=404 "c404"`, 383 } 384 want := strings.Join(wantSegments, "\n") 385 testRedirectsByMethod(t, "POST", postRedirectTests, want) 386 } 387 388 func TestDeleteRedirects(t *testing.T) { 389 deleteRedirectTests := []redirectTest{ 390 {"/", 200, "first"}, 391 {"/?code=301&next=302,308", 200, "c301"}, 392 {"/?code=302&next=302", 200, "c302"}, 393 {"/?code=303", 200, "c303"}, 394 {"/?code=307&next=301,308,303,302,304", 304, "c307"}, 395 {"/?code=308&next=307", 200, "c308"}, 396 {"/?code=404", 404, "c404"}, 397 } 398 399 wantSegments := []string{ 400 `DELETE / "first"`, 401 `DELETE /?code=301&next=302,308 "c301"`, 402 `GET /?code=302&next=308 ""`, 403 `GET /?code=308 ""`, 404 `GET / "c301"`, 405 `DELETE /?code=302&next=302 "c302"`, 406 `GET /?code=302 ""`, 407 `GET / ""`, 408 `DELETE /?code=303 "c303"`, 409 `GET / ""`, 410 `DELETE /?code=307&next=301,308,303,302,304 "c307"`, 411 `DELETE /?code=301&next=308,303,302,304 "c307"`, 412 `GET /?code=308&next=303,302,304 ""`, 413 `GET /?code=303&next=302,304 "c307"`, 414 `GET /?code=302&next=304 ""`, 415 `GET /?code=304 ""`, 416 `DELETE /?code=308&next=307 "c308"`, 417 `DELETE /?code=307 "c308"`, 418 `DELETE / "c308"`, 419 `DELETE /?code=404 "c404"`, 420 } 421 want := strings.Join(wantSegments, "\n") 422 testRedirectsByMethod(t, "DELETE", deleteRedirectTests, want) 423 } 424 425 func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, want string) { 426 defer afterTest(t) 427 var log struct { 428 sync.Mutex 429 bytes.Buffer 430 } 431 var ts *httptest.Server 432 ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 433 log.Lock() 434 slurp, _ := ioutil.ReadAll(r.Body) 435 fmt.Fprintf(&log.Buffer, "%s %s %q", r.Method, r.RequestURI, slurp) 436 if cl := r.Header.Get("Content-Length"); r.Method == "GET" && len(slurp) == 0 && (r.ContentLength != 0 || cl != "") { 437 fmt.Fprintf(&log.Buffer, " (but with body=%T, content-length = %v, %q)", r.Body, r.ContentLength, cl) 438 } 439 log.WriteByte('\n') 440 log.Unlock() 441 urlQuery := r.URL.Query() 442 if v := urlQuery.Get("code"); v != "" { 443 location := ts.URL 444 if final := urlQuery.Get("next"); final != "" { 445 splits := strings.Split(final, ",") 446 first, rest := splits[0], splits[1:] 447 location = fmt.Sprintf("%s?code=%s", location, first) 448 if len(rest) > 0 { 449 location = fmt.Sprintf("%s&next=%s", location, strings.Join(rest, ",")) 450 } 451 } 452 code, _ := strconv.Atoi(v) 453 if code/100 == 3 { 454 w.Header().Set("Location", location) 455 } 456 w.WriteHeader(code) 457 } 458 })) 459 defer ts.Close() 460 461 for _, tt := range table { 462 content := tt.redirectBody 463 req, _ := NewRequest(method, ts.URL+tt.suffix, strings.NewReader(content)) 464 req.GetBody = func() (io.ReadCloser, error) { return ioutil.NopCloser(strings.NewReader(content)), nil } 465 res, err := DefaultClient.Do(req) 466 467 if err != nil { 468 t.Fatal(err) 469 } 470 if res.StatusCode != tt.want { 471 t.Errorf("POST %s: status code = %d; want %d", tt.suffix, res.StatusCode, tt.want) 472 } 473 } 474 log.Lock() 475 got := log.String() 476 log.Unlock() 477 478 got = strings.TrimSpace(got) 479 want = strings.TrimSpace(want) 480 481 if got != want { 482 got, want, lines := removeCommonLines(got, want) 483 t.Errorf("Log differs after %d common lines.\n\nGot:\n%s\n\nWant:\n%s\n", lines, got, want) 484 } 485 } 486 487 func removeCommonLines(a, b string) (asuffix, bsuffix string, commonLines int) { 488 for { 489 nl := strings.IndexByte(a, '\n') 490 if nl < 0 { 491 return a, b, commonLines 492 } 493 line := a[:nl+1] 494 if !strings.HasPrefix(b, line) { 495 return a, b, commonLines 496 } 497 commonLines++ 498 a = a[len(line):] 499 b = b[len(line):] 500 } 501 } 502 503 func TestClientRedirectUseResponse(t *testing.T) { 504 setParallel(t) 505 defer afterTest(t) 506 const body = "Hello, world." 507 var ts *httptest.Server 508 ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 509 if strings.Contains(r.URL.Path, "/other") { 510 io.WriteString(w, "wrong body") 511 } else { 512 w.Header().Set("Location", ts.URL+"/other") 513 w.WriteHeader(StatusFound) 514 io.WriteString(w, body) 515 } 516 })) 517 defer ts.Close() 518 519 tr := &Transport{} 520 defer tr.CloseIdleConnections() 521 522 c := &Client{ 523 Transport: tr, 524 CheckRedirect: func(req *Request, via []*Request) error { 525 if req.Response == nil { 526 t.Error("expected non-nil Request.Response") 527 } 528 return ErrUseLastResponse 529 }, 530 } 531 res, err := c.Get(ts.URL) 532 if err != nil { 533 t.Fatal(err) 534 } 535 if res.StatusCode != StatusFound { 536 t.Errorf("status = %d; want %d", res.StatusCode, StatusFound) 537 } 538 defer res.Body.Close() 539 slurp, err := ioutil.ReadAll(res.Body) 540 if err != nil { 541 t.Fatal(err) 542 } 543 if string(slurp) != body { 544 t.Errorf("body = %q; want %q", slurp, body) 545 } 546 } 547 548 // Issue 17773: don't follow a 308 (or 307) if the response doesn't 549 // have a Location header. 550 func TestClientRedirect308NoLocation(t *testing.T) { 551 setParallel(t) 552 defer afterTest(t) 553 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 554 w.Header().Set("Foo", "Bar") 555 w.WriteHeader(308) 556 })) 557 defer ts.Close() 558 res, err := Get(ts.URL) 559 if err != nil { 560 t.Fatal(err) 561 } 562 res.Body.Close() 563 if res.StatusCode != 308 { 564 t.Errorf("status = %d; want %d", res.StatusCode, 308) 565 } 566 if got := res.Header.Get("Foo"); got != "Bar" { 567 t.Errorf("Foo header = %q; want Bar", got) 568 } 569 } 570 571 // Don't follow a 307/308 if we can't resent the request body. 572 func TestClientRedirect308NoGetBody(t *testing.T) { 573 setParallel(t) 574 defer afterTest(t) 575 const fakeURL = "https://localhost:1234/" // won't be hit 576 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 577 w.Header().Set("Location", fakeURL) 578 w.WriteHeader(308) 579 })) 580 defer ts.Close() 581 req, err := NewRequest("POST", ts.URL, strings.NewReader("some body")) 582 if err != nil { 583 t.Fatal(err) 584 } 585 req.GetBody = nil // so it can't rewind. 586 res, err := DefaultClient.Do(req) 587 if err != nil { 588 t.Fatal(err) 589 } 590 res.Body.Close() 591 if res.StatusCode != 308 { 592 t.Errorf("status = %d; want %d", res.StatusCode, 308) 593 } 594 if got := res.Header.Get("Location"); got != fakeURL { 595 t.Errorf("Location header = %q; want %q", got, fakeURL) 596 } 597 } 598 599 var expectedCookies = []*Cookie{ 600 {Name: "ChocolateChip", Value: "tasty"}, 601 {Name: "First", Value: "Hit"}, 602 {Name: "Second", Value: "Hit"}, 603 } 604 605 var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) { 606 for _, cookie := range r.Cookies() { 607 SetCookie(w, cookie) 608 } 609 if r.URL.Path == "/" { 610 SetCookie(w, expectedCookies[1]) 611 Redirect(w, r, "/second", StatusMovedPermanently) 612 } else { 613 SetCookie(w, expectedCookies[2]) 614 w.Write([]byte("hello")) 615 } 616 }) 617 618 func TestClientSendsCookieFromJar(t *testing.T) { 619 defer afterTest(t) 620 tr := &recordingTransport{} 621 client := &Client{Transport: tr} 622 client.Jar = &TestJar{perURL: make(map[string][]*Cookie)} 623 us := "http://dummy.faketld/" 624 u, _ := url.Parse(us) 625 client.Jar.SetCookies(u, expectedCookies) 626 627 client.Get(us) // Note: doesn't hit network 628 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 629 630 client.Head(us) // Note: doesn't hit network 631 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 632 633 client.Post(us, "text/plain", strings.NewReader("body")) // Note: doesn't hit network 634 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 635 636 client.PostForm(us, url.Values{}) // Note: doesn't hit network 637 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 638 639 req, _ := NewRequest("GET", us, nil) 640 client.Do(req) // Note: doesn't hit network 641 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 642 643 req, _ = NewRequest("POST", us, nil) 644 client.Do(req) // Note: doesn't hit network 645 matchReturnedCookies(t, expectedCookies, tr.req.Cookies()) 646 } 647 648 // Just enough correctness for our redirect tests. Uses the URL.Host as the 649 // scope of all cookies. 650 type TestJar struct { 651 m sync.Mutex 652 perURL map[string][]*Cookie 653 } 654 655 func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) { 656 j.m.Lock() 657 defer j.m.Unlock() 658 if j.perURL == nil { 659 j.perURL = make(map[string][]*Cookie) 660 } 661 j.perURL[u.Host] = cookies 662 } 663 664 func (j *TestJar) Cookies(u *url.URL) []*Cookie { 665 j.m.Lock() 666 defer j.m.Unlock() 667 return j.perURL[u.Host] 668 } 669 670 func TestRedirectCookiesJar(t *testing.T) { 671 setParallel(t) 672 defer afterTest(t) 673 var ts *httptest.Server 674 ts = httptest.NewServer(echoCookiesRedirectHandler) 675 defer ts.Close() 676 tr := &Transport{} 677 defer tr.CloseIdleConnections() 678 c := &Client{ 679 Transport: tr, 680 Jar: new(TestJar), 681 } 682 u, _ := url.Parse(ts.URL) 683 c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]}) 684 resp, err := c.Get(ts.URL) 685 if err != nil { 686 t.Fatalf("Get: %v", err) 687 } 688 resp.Body.Close() 689 matchReturnedCookies(t, expectedCookies, resp.Cookies()) 690 } 691 692 func matchReturnedCookies(t *testing.T, expected, given []*Cookie) { 693 if len(given) != len(expected) { 694 t.Logf("Received cookies: %v", given) 695 t.Errorf("Expected %d cookies, got %d", len(expected), len(given)) 696 } 697 for _, ec := range expected { 698 foundC := false 699 for _, c := range given { 700 if ec.Name == c.Name && ec.Value == c.Value { 701 foundC = true 702 break 703 } 704 } 705 if !foundC { 706 t.Errorf("Missing cookie %v", ec) 707 } 708 } 709 } 710 711 func TestJarCalls(t *testing.T) { 712 defer afterTest(t) 713 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 714 pathSuffix := r.RequestURI[1:] 715 if r.RequestURI == "/nosetcookie" { 716 return // don't set cookies for this path 717 } 718 SetCookie(w, &Cookie{Name: "name" + pathSuffix, Value: "val" + pathSuffix}) 719 if r.RequestURI == "/" { 720 Redirect(w, r, "http://secondhost.fake/secondpath", 302) 721 } 722 })) 723 defer ts.Close() 724 jar := new(RecordingJar) 725 c := &Client{ 726 Jar: jar, 727 Transport: &Transport{ 728 Dial: func(_ string, _ string) (net.Conn, error) { 729 return net.Dial("tcp", ts.Listener.Addr().String()) 730 }, 731 }, 732 } 733 _, err := c.Get("http://firsthost.fake/") 734 if err != nil { 735 t.Fatal(err) 736 } 737 _, err = c.Get("http://firsthost.fake/nosetcookie") 738 if err != nil { 739 t.Fatal(err) 740 } 741 got := jar.log.String() 742 want := `Cookies("http://firsthost.fake/") 743 SetCookie("http://firsthost.fake/", [name=val]) 744 Cookies("http://secondhost.fake/secondpath") 745 SetCookie("http://secondhost.fake/secondpath", [namesecondpath=valsecondpath]) 746 Cookies("http://firsthost.fake/nosetcookie") 747 ` 748 if got != want { 749 t.Errorf("Got Jar calls:\n%s\nWant:\n%s", got, want) 750 } 751 } 752 753 // RecordingJar keeps a log of calls made to it, without 754 // tracking any cookies. 755 type RecordingJar struct { 756 mu sync.Mutex 757 log bytes.Buffer 758 } 759 760 func (j *RecordingJar) SetCookies(u *url.URL, cookies []*Cookie) { 761 j.logf("SetCookie(%q, %v)\n", u, cookies) 762 } 763 764 func (j *RecordingJar) Cookies(u *url.URL) []*Cookie { 765 j.logf("Cookies(%q)\n", u) 766 return nil 767 } 768 769 func (j *RecordingJar) logf(format string, args ...interface{}) { 770 j.mu.Lock() 771 defer j.mu.Unlock() 772 fmt.Fprintf(&j.log, format, args...) 773 } 774 775 func TestStreamingGet_h1(t *testing.T) { testStreamingGet(t, h1Mode) } 776 func TestStreamingGet_h2(t *testing.T) { testStreamingGet(t, h2Mode) } 777 778 func testStreamingGet(t *testing.T, h2 bool) { 779 defer afterTest(t) 780 say := make(chan string) 781 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 782 w.(Flusher).Flush() 783 for str := range say { 784 w.Write([]byte(str)) 785 w.(Flusher).Flush() 786 } 787 })) 788 defer cst.close() 789 790 c := cst.c 791 res, err := c.Get(cst.ts.URL) 792 if err != nil { 793 t.Fatal(err) 794 } 795 var buf [10]byte 796 for _, str := range []string{"i", "am", "also", "known", "as", "comet"} { 797 say <- str 798 n, err := io.ReadFull(res.Body, buf[0:len(str)]) 799 if err != nil { 800 t.Fatalf("ReadFull on %q: %v", str, err) 801 } 802 if n != len(str) { 803 t.Fatalf("Receiving %q, only read %d bytes", str, n) 804 } 805 got := string(buf[0:n]) 806 if got != str { 807 t.Fatalf("Expected %q, got %q", str, got) 808 } 809 } 810 close(say) 811 _, err = io.ReadFull(res.Body, buf[0:1]) 812 if err != io.EOF { 813 t.Fatalf("at end expected EOF, got %v", err) 814 } 815 } 816 817 type writeCountingConn struct { 818 net.Conn 819 count *int 820 } 821 822 func (c *writeCountingConn) Write(p []byte) (int, error) { 823 *c.count++ 824 return c.Conn.Write(p) 825 } 826 827 // TestClientWrites verifies that client requests are buffered and we 828 // don't send a TCP packet per line of the http request + body. 829 func TestClientWrites(t *testing.T) { 830 defer afterTest(t) 831 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 832 })) 833 defer ts.Close() 834 835 writes := 0 836 dialer := func(netz string, addr string) (net.Conn, error) { 837 c, err := net.Dial(netz, addr) 838 if err == nil { 839 c = &writeCountingConn{c, &writes} 840 } 841 return c, err 842 } 843 c := &Client{Transport: &Transport{Dial: dialer}} 844 845 _, err := c.Get(ts.URL) 846 if err != nil { 847 t.Fatal(err) 848 } 849 if writes != 1 { 850 t.Errorf("Get request did %d Write calls, want 1", writes) 851 } 852 853 writes = 0 854 _, err = c.PostForm(ts.URL, url.Values{"foo": {"bar"}}) 855 if err != nil { 856 t.Fatal(err) 857 } 858 if writes != 1 { 859 t.Errorf("Post request did %d Write calls, want 1", writes) 860 } 861 } 862 863 func TestClientInsecureTransport(t *testing.T) { 864 setParallel(t) 865 defer afterTest(t) 866 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 867 w.Write([]byte("Hello")) 868 })) 869 errc := make(chanWriter, 10) // but only expecting 1 870 ts.Config.ErrorLog = log.New(errc, "", 0) 871 defer ts.Close() 872 873 // TODO(bradfitz): add tests for skipping hostname checks too? 874 // would require a new cert for testing, and probably 875 // redundant with these tests. 876 for _, insecure := range []bool{true, false} { 877 tr := &Transport{ 878 TLSClientConfig: &tls.Config{ 879 InsecureSkipVerify: insecure, 880 }, 881 } 882 defer tr.CloseIdleConnections() 883 c := &Client{Transport: tr} 884 res, err := c.Get(ts.URL) 885 if (err == nil) != insecure { 886 t.Errorf("insecure=%v: got unexpected err=%v", insecure, err) 887 } 888 if res != nil { 889 res.Body.Close() 890 } 891 } 892 893 select { 894 case v := <-errc: 895 if !strings.Contains(v, "TLS handshake error") { 896 t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v) 897 } 898 case <-time.After(5 * time.Second): 899 t.Errorf("timeout waiting for logged error") 900 } 901 902 } 903 904 func TestClientErrorWithRequestURI(t *testing.T) { 905 defer afterTest(t) 906 req, _ := NewRequest("GET", "http://localhost:1234/", nil) 907 req.RequestURI = "/this/field/is/illegal/and/should/error/" 908 _, err := DefaultClient.Do(req) 909 if err == nil { 910 t.Fatalf("expected an error") 911 } 912 if !strings.Contains(err.Error(), "RequestURI") { 913 t.Errorf("wanted error mentioning RequestURI; got error: %v", err) 914 } 915 } 916 917 func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport { 918 certs := x509.NewCertPool() 919 for _, c := range ts.TLS.Certificates { 920 roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1]) 921 if err != nil { 922 t.Fatalf("error parsing server's root cert: %v", err) 923 } 924 for _, root := range roots { 925 certs.AddCert(root) 926 } 927 } 928 return &Transport{ 929 TLSClientConfig: &tls.Config{RootCAs: certs}, 930 } 931 } 932 933 func TestClientWithCorrectTLSServerName(t *testing.T) { 934 defer afterTest(t) 935 936 const serverName = "example.com" 937 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 938 if r.TLS.ServerName != serverName { 939 t.Errorf("expected client to set ServerName %q, got: %q", serverName, r.TLS.ServerName) 940 } 941 })) 942 defer ts.Close() 943 944 trans := newTLSTransport(t, ts) 945 trans.TLSClientConfig.ServerName = serverName 946 c := &Client{Transport: trans} 947 if _, err := c.Get(ts.URL); err != nil { 948 t.Fatalf("expected successful TLS connection, got error: %v", err) 949 } 950 } 951 952 func TestClientWithIncorrectTLSServerName(t *testing.T) { 953 defer afterTest(t) 954 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 955 defer ts.Close() 956 errc := make(chanWriter, 10) // but only expecting 1 957 ts.Config.ErrorLog = log.New(errc, "", 0) 958 959 trans := newTLSTransport(t, ts) 960 trans.TLSClientConfig.ServerName = "badserver" 961 c := &Client{Transport: trans} 962 _, err := c.Get(ts.URL) 963 if err == nil { 964 t.Fatalf("expected an error") 965 } 966 if !strings.Contains(err.Error(), "127.0.0.1") || !strings.Contains(err.Error(), "badserver") { 967 t.Errorf("wanted error mentioning 127.0.0.1 and badserver; got error: %v", err) 968 } 969 select { 970 case v := <-errc: 971 if !strings.Contains(v, "TLS handshake error") { 972 t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v) 973 } 974 case <-time.After(5 * time.Second): 975 t.Errorf("timeout waiting for logged error") 976 } 977 } 978 979 // Test for golang.org/issue/5829; the Transport should respect TLSClientConfig.ServerName 980 // when not empty. 981 // 982 // tls.Config.ServerName (non-empty, set to "example.com") takes 983 // precedence over "some-other-host.tld" which previously incorrectly 984 // took precedence. We don't actually connect to (or even resolve) 985 // "some-other-host.tld", though, because of the Transport.Dial hook. 986 // 987 // The httptest.Server has a cert with "example.com" as its name. 988 func TestTransportUsesTLSConfigServerName(t *testing.T) { 989 defer afterTest(t) 990 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 991 w.Write([]byte("Hello")) 992 })) 993 defer ts.Close() 994 995 tr := newTLSTransport(t, ts) 996 tr.TLSClientConfig.ServerName = "example.com" // one of httptest's Server cert names 997 tr.Dial = func(netw, addr string) (net.Conn, error) { 998 return net.Dial(netw, ts.Listener.Addr().String()) 999 } 1000 defer tr.CloseIdleConnections() 1001 c := &Client{Transport: tr} 1002 res, err := c.Get("https://some-other-host.tld/") 1003 if err != nil { 1004 t.Fatal(err) 1005 } 1006 res.Body.Close() 1007 } 1008 1009 func TestResponseSetsTLSConnectionState(t *testing.T) { 1010 defer afterTest(t) 1011 ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1012 w.Write([]byte("Hello")) 1013 })) 1014 defer ts.Close() 1015 1016 tr := newTLSTransport(t, ts) 1017 tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} 1018 tr.Dial = func(netw, addr string) (net.Conn, error) { 1019 return net.Dial(netw, ts.Listener.Addr().String()) 1020 } 1021 defer tr.CloseIdleConnections() 1022 c := &Client{Transport: tr} 1023 res, err := c.Get("https://example.com/") 1024 if err != nil { 1025 t.Fatal(err) 1026 } 1027 defer res.Body.Close() 1028 if res.TLS == nil { 1029 t.Fatal("Response didn't set TLS Connection State.") 1030 } 1031 if got, want := res.TLS.CipherSuite, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA; got != want { 1032 t.Errorf("TLS Cipher Suite = %d; want %d", got, want) 1033 } 1034 } 1035 1036 // Check that an HTTPS client can interpret a particular TLS error 1037 // to determine that the server is speaking HTTP. 1038 // See golang.org/issue/11111. 1039 func TestHTTPSClientDetectsHTTPServer(t *testing.T) { 1040 defer afterTest(t) 1041 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) 1042 ts.Config.ErrorLog = quietLog 1043 defer ts.Close() 1044 1045 _, err := Get(strings.Replace(ts.URL, "http", "https", 1)) 1046 if got := err.Error(); !strings.Contains(got, "HTTP response to HTTPS client") { 1047 t.Fatalf("error = %q; want error indicating HTTP response to HTTPS request", got) 1048 } 1049 } 1050 1051 // Verify Response.ContentLength is populated. https://golang.org/issue/4126 1052 func TestClientHeadContentLength_h1(t *testing.T) { 1053 testClientHeadContentLength(t, h1Mode) 1054 } 1055 1056 func TestClientHeadContentLength_h2(t *testing.T) { 1057 testClientHeadContentLength(t, h2Mode) 1058 } 1059 1060 func testClientHeadContentLength(t *testing.T, h2 bool) { 1061 defer afterTest(t) 1062 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1063 if v := r.FormValue("cl"); v != "" { 1064 w.Header().Set("Content-Length", v) 1065 } 1066 })) 1067 defer cst.close() 1068 tests := []struct { 1069 suffix string 1070 want int64 1071 }{ 1072 {"/?cl=1234", 1234}, 1073 {"/?cl=0", 0}, 1074 {"", -1}, 1075 } 1076 for _, tt := range tests { 1077 req, _ := NewRequest("HEAD", cst.ts.URL+tt.suffix, nil) 1078 res, err := cst.c.Do(req) 1079 if err != nil { 1080 t.Fatal(err) 1081 } 1082 if res.ContentLength != tt.want { 1083 t.Errorf("Content-Length = %d; want %d", res.ContentLength, tt.want) 1084 } 1085 bs, err := ioutil.ReadAll(res.Body) 1086 if err != nil { 1087 t.Fatal(err) 1088 } 1089 if len(bs) != 0 { 1090 t.Errorf("Unexpected content: %q", bs) 1091 } 1092 } 1093 } 1094 1095 func TestEmptyPasswordAuth(t *testing.T) { 1096 setParallel(t) 1097 defer afterTest(t) 1098 gopher := "gopher" 1099 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1100 auth := r.Header.Get("Authorization") 1101 if strings.HasPrefix(auth, "Basic ") { 1102 encoded := auth[6:] 1103 decoded, err := base64.StdEncoding.DecodeString(encoded) 1104 if err != nil { 1105 t.Fatal(err) 1106 } 1107 expected := gopher + ":" 1108 s := string(decoded) 1109 if expected != s { 1110 t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected) 1111 } 1112 } else { 1113 t.Errorf("Invalid auth %q", auth) 1114 } 1115 })) 1116 defer ts.Close() 1117 tr := &Transport{} 1118 defer tr.CloseIdleConnections() 1119 c := &Client{Transport: tr} 1120 req, err := NewRequest("GET", ts.URL, nil) 1121 if err != nil { 1122 t.Fatal(err) 1123 } 1124 req.URL.User = url.User(gopher) 1125 resp, err := c.Do(req) 1126 if err != nil { 1127 t.Fatal(err) 1128 } 1129 defer resp.Body.Close() 1130 } 1131 1132 func TestBasicAuth(t *testing.T) { 1133 defer afterTest(t) 1134 tr := &recordingTransport{} 1135 client := &Client{Transport: tr} 1136 1137 url := "http://My%20User:My%20Pass@dummy.faketld/" 1138 expected := "My User:My Pass" 1139 client.Get(url) 1140 1141 if tr.req.Method != "GET" { 1142 t.Errorf("got method %q, want %q", tr.req.Method, "GET") 1143 } 1144 if tr.req.URL.String() != url { 1145 t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) 1146 } 1147 if tr.req.Header == nil { 1148 t.Fatalf("expected non-nil request Header") 1149 } 1150 auth := tr.req.Header.Get("Authorization") 1151 if strings.HasPrefix(auth, "Basic ") { 1152 encoded := auth[6:] 1153 decoded, err := base64.StdEncoding.DecodeString(encoded) 1154 if err != nil { 1155 t.Fatal(err) 1156 } 1157 s := string(decoded) 1158 if expected != s { 1159 t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected) 1160 } 1161 } else { 1162 t.Errorf("Invalid auth %q", auth) 1163 } 1164 } 1165 1166 func TestBasicAuthHeadersPreserved(t *testing.T) { 1167 defer afterTest(t) 1168 tr := &recordingTransport{} 1169 client := &Client{Transport: tr} 1170 1171 // If Authorization header is provided, username in URL should not override it 1172 url := "http://My%20User@dummy.faketld/" 1173 req, err := NewRequest("GET", url, nil) 1174 if err != nil { 1175 t.Fatal(err) 1176 } 1177 req.SetBasicAuth("My User", "My Pass") 1178 expected := "My User:My Pass" 1179 client.Do(req) 1180 1181 if tr.req.Method != "GET" { 1182 t.Errorf("got method %q, want %q", tr.req.Method, "GET") 1183 } 1184 if tr.req.URL.String() != url { 1185 t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) 1186 } 1187 if tr.req.Header == nil { 1188 t.Fatalf("expected non-nil request Header") 1189 } 1190 auth := tr.req.Header.Get("Authorization") 1191 if strings.HasPrefix(auth, "Basic ") { 1192 encoded := auth[6:] 1193 decoded, err := base64.StdEncoding.DecodeString(encoded) 1194 if err != nil { 1195 t.Fatal(err) 1196 } 1197 s := string(decoded) 1198 if expected != s { 1199 t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected) 1200 } 1201 } else { 1202 t.Errorf("Invalid auth %q", auth) 1203 } 1204 1205 } 1206 1207 func TestClientTimeout_h1(t *testing.T) { testClientTimeout(t, h1Mode) } 1208 func TestClientTimeout_h2(t *testing.T) { testClientTimeout(t, h2Mode) } 1209 1210 func testClientTimeout(t *testing.T, h2 bool) { 1211 setParallel(t) 1212 defer afterTest(t) 1213 testDone := make(chan struct{}) // closed in defer below 1214 1215 sawRoot := make(chan bool, 1) 1216 sawSlow := make(chan bool, 1) 1217 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1218 if r.URL.Path == "/" { 1219 sawRoot <- true 1220 Redirect(w, r, "/slow", StatusFound) 1221 return 1222 } 1223 if r.URL.Path == "/slow" { 1224 sawSlow <- true 1225 w.Write([]byte("Hello")) 1226 w.(Flusher).Flush() 1227 <-testDone 1228 return 1229 } 1230 })) 1231 defer cst.close() 1232 defer close(testDone) // before cst.close, to unblock /slow handler 1233 1234 // 200ms should be long enough to get a normal request (the / 1235 // handler), but not so long that it makes the test slow. 1236 const timeout = 200 * time.Millisecond 1237 cst.c.Timeout = timeout 1238 1239 res, err := cst.c.Get(cst.ts.URL) 1240 if err != nil { 1241 if strings.Contains(err.Error(), "Client.Timeout") { 1242 t.Skipf("host too slow to get fast resource in %v", timeout) 1243 } 1244 t.Fatal(err) 1245 } 1246 1247 select { 1248 case <-sawRoot: 1249 // good. 1250 default: 1251 t.Fatal("handler never got / request") 1252 } 1253 1254 select { 1255 case <-sawSlow: 1256 // good. 1257 default: 1258 t.Fatal("handler never got /slow request") 1259 } 1260 1261 errc := make(chan error, 1) 1262 go func() { 1263 _, err := ioutil.ReadAll(res.Body) 1264 errc <- err 1265 res.Body.Close() 1266 }() 1267 1268 const failTime = 5 * time.Second 1269 select { 1270 case err := <-errc: 1271 if err == nil { 1272 t.Fatal("expected error from ReadAll") 1273 } 1274 ne, ok := err.(net.Error) 1275 if !ok { 1276 t.Errorf("error value from ReadAll was %T; expected some net.Error", err) 1277 } else if !ne.Timeout() { 1278 t.Errorf("net.Error.Timeout = false; want true") 1279 } 1280 if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") { 1281 t.Errorf("error string = %q; missing timeout substring", got) 1282 } 1283 case <-time.After(failTime): 1284 t.Errorf("timeout after %v waiting for timeout of %v", failTime, timeout) 1285 } 1286 } 1287 1288 func TestClientTimeout_Headers_h1(t *testing.T) { testClientTimeout_Headers(t, h1Mode) } 1289 func TestClientTimeout_Headers_h2(t *testing.T) { testClientTimeout_Headers(t, h2Mode) } 1290 1291 // Client.Timeout firing before getting to the body 1292 func testClientTimeout_Headers(t *testing.T, h2 bool) { 1293 setParallel(t) 1294 defer afterTest(t) 1295 donec := make(chan bool, 1) 1296 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1297 <-donec 1298 })) 1299 defer cst.close() 1300 // Note that we use a channel send here and not a close. 1301 // The race detector doesn't know that we're waiting for a timeout 1302 // and thinks that the waitgroup inside httptest.Server is added to concurrently 1303 // with us closing it. If we timed out immediately, we could close the testserver 1304 // before we entered the handler. We're not timing out immediately and there's 1305 // no way we would be done before we entered the handler, but the race detector 1306 // doesn't know this, so synchronize explicitly. 1307 defer func() { donec <- true }() 1308 1309 cst.c.Timeout = 5 * time.Millisecond 1310 res, err := cst.c.Get(cst.ts.URL) 1311 if err == nil { 1312 res.Body.Close() 1313 t.Fatal("got response from Get; expected error") 1314 } 1315 if _, ok := err.(*url.Error); !ok { 1316 t.Fatalf("Got error of type %T; want *url.Error", err) 1317 } 1318 ne, ok := err.(net.Error) 1319 if !ok { 1320 t.Fatalf("Got error of type %T; want some net.Error", err) 1321 } 1322 if !ne.Timeout() { 1323 t.Error("net.Error.Timeout = false; want true") 1324 } 1325 if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") { 1326 t.Errorf("error string = %q; missing timeout substring", got) 1327 } 1328 } 1329 1330 // Issue 16094: if Client.Timeout is set but not hit, a Timeout error shouldn't be 1331 // returned. 1332 func TestClientTimeoutCancel(t *testing.T) { 1333 setParallel(t) 1334 defer afterTest(t) 1335 1336 testDone := make(chan struct{}) 1337 ctx, cancel := context.WithCancel(context.Background()) 1338 1339 cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { 1340 w.(Flusher).Flush() 1341 <-testDone 1342 })) 1343 defer cst.close() 1344 defer close(testDone) 1345 1346 cst.c.Timeout = 1 * time.Hour 1347 req, _ := NewRequest("GET", cst.ts.URL, nil) 1348 req.Cancel = ctx.Done() 1349 res, err := cst.c.Do(req) 1350 if err != nil { 1351 t.Fatal(err) 1352 } 1353 cancel() 1354 _, err = io.Copy(ioutil.Discard, res.Body) 1355 if err != ExportErrRequestCanceled { 1356 t.Fatalf("error = %v; want errRequestCanceled", err) 1357 } 1358 } 1359 1360 func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) } 1361 func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) } 1362 func testClientRedirectEatsBody(t *testing.T, h2 bool) { 1363 setParallel(t) 1364 defer afterTest(t) 1365 saw := make(chan string, 2) 1366 cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { 1367 saw <- r.RemoteAddr 1368 if r.URL.Path == "/" { 1369 Redirect(w, r, "/foo", StatusFound) // which includes a body 1370 } 1371 })) 1372 defer cst.close() 1373 1374 res, err := cst.c.Get(cst.ts.URL) 1375 if err != nil { 1376 t.Fatal(err) 1377 } 1378 _, err = ioutil.ReadAll(res.Body) 1379 res.Body.Close() 1380 if err != nil { 1381 t.Fatal(err) 1382 } 1383 1384 var first string 1385 select { 1386 case first = <-saw: 1387 default: 1388 t.Fatal("server didn't see a request") 1389 } 1390 1391 var second string 1392 select { 1393 case second = <-saw: 1394 default: 1395 t.Fatal("server didn't see a second request") 1396 } 1397 1398 if first != second { 1399 t.Fatal("server saw different client ports before & after the redirect") 1400 } 1401 } 1402 1403 // eofReaderFunc is an io.Reader that runs itself, and then returns io.EOF. 1404 type eofReaderFunc func() 1405 1406 func (f eofReaderFunc) Read(p []byte) (n int, err error) { 1407 f() 1408 return 0, io.EOF 1409 } 1410 1411 func TestReferer(t *testing.T) { 1412 tests := []struct { 1413 lastReq, newReq string // from -> to URLs 1414 want string 1415 }{ 1416 // don't send user: 1417 {"http://gopher@test.com", "http://link.com", "http://test.com"}, 1418 {"https://gopher@test.com", "https://link.com", "https://test.com"}, 1419 1420 // don't send a user and password: 1421 {"http://gopher:go@test.com", "http://link.com", "http://test.com"}, 1422 {"https://gopher:go@test.com", "https://link.com", "https://test.com"}, 1423 1424 // nothing to do: 1425 {"http://test.com", "http://link.com", "http://test.com"}, 1426 {"https://test.com", "https://link.com", "https://test.com"}, 1427 1428 // https to http doesn't send a referer: 1429 {"https://test.com", "http://link.com", ""}, 1430 {"https://gopher:go@test.com", "http://link.com", ""}, 1431 } 1432 for _, tt := range tests { 1433 l, err := url.Parse(tt.lastReq) 1434 if err != nil { 1435 t.Fatal(err) 1436 } 1437 n, err := url.Parse(tt.newReq) 1438 if err != nil { 1439 t.Fatal(err) 1440 } 1441 r := ExportRefererForURL(l, n) 1442 if r != tt.want { 1443 t.Errorf("refererForURL(%q, %q) = %q; want %q", tt.lastReq, tt.newReq, r, tt.want) 1444 } 1445 } 1446 } 1447 1448 // issue15577Tripper returns a Response with a redirect response 1449 // header and doesn't populate its Response.Request field. 1450 type issue15577Tripper struct{} 1451 1452 func (issue15577Tripper) RoundTrip(*Request) (*Response, error) { 1453 resp := &Response{ 1454 StatusCode: 303, 1455 Header: map[string][]string{"Location": {"http://www.example.com/"}}, 1456 Body: ioutil.NopCloser(strings.NewReader("")), 1457 } 1458 return resp, nil 1459 } 1460 1461 // Issue 15577: don't assume the roundtripper's response populates its Request field. 1462 func TestClientRedirectResponseWithoutRequest(t *testing.T) { 1463 c := &Client{ 1464 CheckRedirect: func(*Request, []*Request) error { return fmt.Errorf("no redirects!") }, 1465 Transport: issue15577Tripper{}, 1466 } 1467 // Check that this doesn't crash: 1468 c.Get("http://dummy.tld") 1469 } 1470 1471 // Issue 4800: copy (some) headers when Client follows a redirect 1472 func TestClientCopyHeadersOnRedirect(t *testing.T) { 1473 const ( 1474 ua = "some-agent/1.2" 1475 xfoo = "foo-val" 1476 ) 1477 var ts2URL string 1478 ts1 := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1479 want := Header{ 1480 "User-Agent": []string{ua}, 1481 "X-Foo": []string{xfoo}, 1482 "Referer": []string{ts2URL}, 1483 "Accept-Encoding": []string{"gzip"}, 1484 } 1485 if !reflect.DeepEqual(r.Header, want) { 1486 t.Errorf("Request.Header = %#v; want %#v", r.Header, want) 1487 } 1488 if t.Failed() { 1489 w.Header().Set("Result", "got errors") 1490 } else { 1491 w.Header().Set("Result", "ok") 1492 } 1493 })) 1494 defer ts1.Close() 1495 ts2 := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1496 Redirect(w, r, ts1.URL, StatusFound) 1497 })) 1498 defer ts2.Close() 1499 ts2URL = ts2.URL 1500 1501 tr := &Transport{} 1502 defer tr.CloseIdleConnections() 1503 c := &Client{ 1504 Transport: tr, 1505 CheckRedirect: func(r *Request, via []*Request) error { 1506 want := Header{ 1507 "User-Agent": []string{ua}, 1508 "X-Foo": []string{xfoo}, 1509 "Referer": []string{ts2URL}, 1510 } 1511 if !reflect.DeepEqual(r.Header, want) { 1512 t.Errorf("CheckRedirect Request.Header = %#v; want %#v", r.Header, want) 1513 } 1514 return nil 1515 }, 1516 } 1517 1518 req, _ := NewRequest("GET", ts2.URL, nil) 1519 req.Header.Add("User-Agent", ua) 1520 req.Header.Add("X-Foo", xfoo) 1521 req.Header.Add("Cookie", "foo=bar") 1522 req.Header.Add("Authorization", "secretpassword") 1523 res, err := c.Do(req) 1524 if err != nil { 1525 t.Fatal(err) 1526 } 1527 defer res.Body.Close() 1528 if res.StatusCode != 200 { 1529 t.Fatal(res.Status) 1530 } 1531 if got := res.Header.Get("Result"); got != "ok" { 1532 t.Errorf("result = %q; want ok", got) 1533 } 1534 } 1535 1536 // Issue 17494: cookies should be altered when Client follows redirects. 1537 func TestClientAltersCookiesOnRedirect(t *testing.T) { 1538 cookieMap := func(cs []*Cookie) map[string][]string { 1539 m := make(map[string][]string) 1540 for _, c := range cs { 1541 m[c.Name] = append(m[c.Name], c.Value) 1542 } 1543 return m 1544 } 1545 1546 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1547 var want map[string][]string 1548 got := cookieMap(r.Cookies()) 1549 1550 c, _ := r.Cookie("Cycle") 1551 switch c.Value { 1552 case "0": 1553 want = map[string][]string{ 1554 "Cookie1": {"OldValue1a", "OldValue1b"}, 1555 "Cookie2": {"OldValue2"}, 1556 "Cookie3": {"OldValue3a", "OldValue3b"}, 1557 "Cookie4": {"OldValue4"}, 1558 "Cycle": {"0"}, 1559 } 1560 SetCookie(w, &Cookie{Name: "Cycle", Value: "1", Path: "/"}) 1561 SetCookie(w, &Cookie{Name: "Cookie2", Path: "/", MaxAge: -1}) // Delete cookie from Header 1562 Redirect(w, r, "/", StatusFound) 1563 case "1": 1564 want = map[string][]string{ 1565 "Cookie1": {"OldValue1a", "OldValue1b"}, 1566 "Cookie3": {"OldValue3a", "OldValue3b"}, 1567 "Cookie4": {"OldValue4"}, 1568 "Cycle": {"1"}, 1569 } 1570 SetCookie(w, &Cookie{Name: "Cycle", Value: "2", Path: "/"}) 1571 SetCookie(w, &Cookie{Name: "Cookie3", Value: "NewValue3", Path: "/"}) // Modify cookie in Header 1572 SetCookie(w, &Cookie{Name: "Cookie4", Value: "NewValue4", Path: "/"}) // Modify cookie in Jar 1573 Redirect(w, r, "/", StatusFound) 1574 case "2": 1575 want = map[string][]string{ 1576 "Cookie1": {"OldValue1a", "OldValue1b"}, 1577 "Cookie3": {"NewValue3"}, 1578 "Cookie4": {"NewValue4"}, 1579 "Cycle": {"2"}, 1580 } 1581 SetCookie(w, &Cookie{Name: "Cycle", Value: "3", Path: "/"}) 1582 SetCookie(w, &Cookie{Name: "Cookie5", Value: "NewValue5", Path: "/"}) // Insert cookie into Jar 1583 Redirect(w, r, "/", StatusFound) 1584 case "3": 1585 want = map[string][]string{ 1586 "Cookie1": {"OldValue1a", "OldValue1b"}, 1587 "Cookie3": {"NewValue3"}, 1588 "Cookie4": {"NewValue4"}, 1589 "Cookie5": {"NewValue5"}, 1590 "Cycle": {"3"}, 1591 } 1592 // Don't redirect to ensure the loop ends. 1593 default: 1594 t.Errorf("unexpected redirect cycle") 1595 return 1596 } 1597 1598 if !reflect.DeepEqual(got, want) { 1599 t.Errorf("redirect %s, Cookie = %v, want %v", c.Value, got, want) 1600 } 1601 })) 1602 defer ts.Close() 1603 1604 tr := &Transport{} 1605 defer tr.CloseIdleConnections() 1606 jar, _ := cookiejar.New(nil) 1607 c := &Client{ 1608 Transport: tr, 1609 Jar: jar, 1610 } 1611 1612 u, _ := url.Parse(ts.URL) 1613 req, _ := NewRequest("GET", ts.URL, nil) 1614 req.AddCookie(&Cookie{Name: "Cookie1", Value: "OldValue1a"}) 1615 req.AddCookie(&Cookie{Name: "Cookie1", Value: "OldValue1b"}) 1616 req.AddCookie(&Cookie{Name: "Cookie2", Value: "OldValue2"}) 1617 req.AddCookie(&Cookie{Name: "Cookie3", Value: "OldValue3a"}) 1618 req.AddCookie(&Cookie{Name: "Cookie3", Value: "OldValue3b"}) 1619 jar.SetCookies(u, []*Cookie{{Name: "Cookie4", Value: "OldValue4", Path: "/"}}) 1620 jar.SetCookies(u, []*Cookie{{Name: "Cycle", Value: "0", Path: "/"}}) 1621 res, err := c.Do(req) 1622 if err != nil { 1623 t.Fatal(err) 1624 } 1625 defer res.Body.Close() 1626 if res.StatusCode != 200 { 1627 t.Fatal(res.Status) 1628 } 1629 } 1630 1631 // Part of Issue 4800 1632 func TestShouldCopyHeaderOnRedirect(t *testing.T) { 1633 tests := []struct { 1634 header string 1635 initialURL string 1636 destURL string 1637 want bool 1638 }{ 1639 {"User-Agent", "http://foo.com/", "http://bar.com/", true}, 1640 {"X-Foo", "http://foo.com/", "http://bar.com/", true}, 1641 1642 // Sensitive headers: 1643 {"cookie", "http://foo.com/", "http://bar.com/", false}, 1644 {"cookie2", "http://foo.com/", "http://bar.com/", false}, 1645 {"authorization", "http://foo.com/", "http://bar.com/", false}, 1646 {"www-authenticate", "http://foo.com/", "http://bar.com/", false}, 1647 1648 // But subdomains should work: 1649 {"www-authenticate", "http://foo.com/", "http://foo.com/", true}, 1650 {"www-authenticate", "http://foo.com/", "http://sub.foo.com/", true}, 1651 {"www-authenticate", "http://foo.com/", "http://notfoo.com/", false}, 1652 // TODO(bradfitz): make this test work, once issue 16142 is fixed: 1653 // {"www-authenticate", "http://foo.com:80/", "http://foo.com/", true}, 1654 } 1655 for i, tt := range tests { 1656 u0, err := url.Parse(tt.initialURL) 1657 if err != nil { 1658 t.Errorf("%d. initial URL %q parse error: %v", i, tt.initialURL, err) 1659 continue 1660 } 1661 u1, err := url.Parse(tt.destURL) 1662 if err != nil { 1663 t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err) 1664 continue 1665 } 1666 got := Export_shouldCopyHeaderOnRedirect(tt.header, u0, u1) 1667 if got != tt.want { 1668 t.Errorf("%d. shouldCopyHeaderOnRedirect(%q, %q => %q) = %v; want %v", 1669 i, tt.header, tt.initialURL, tt.destURL, got, tt.want) 1670 } 1671 } 1672 } 1673 1674 func TestClientRedirectTypes(t *testing.T) { 1675 setParallel(t) 1676 defer afterTest(t) 1677 1678 tests := [...]struct { 1679 method string 1680 serverStatus int 1681 wantMethod string // desired subsequent client method 1682 }{ 1683 0: {method: "POST", serverStatus: 301, wantMethod: "GET"}, 1684 1: {method: "POST", serverStatus: 302, wantMethod: "GET"}, 1685 2: {method: "POST", serverStatus: 303, wantMethod: "GET"}, 1686 3: {method: "POST", serverStatus: 307, wantMethod: "POST"}, 1687 4: {method: "POST", serverStatus: 308, wantMethod: "POST"}, 1688 1689 5: {method: "HEAD", serverStatus: 301, wantMethod: "HEAD"}, 1690 6: {method: "HEAD", serverStatus: 302, wantMethod: "HEAD"}, 1691 7: {method: "HEAD", serverStatus: 303, wantMethod: "HEAD"}, 1692 8: {method: "HEAD", serverStatus: 307, wantMethod: "HEAD"}, 1693 9: {method: "HEAD", serverStatus: 308, wantMethod: "HEAD"}, 1694 1695 10: {method: "GET", serverStatus: 301, wantMethod: "GET"}, 1696 11: {method: "GET", serverStatus: 302, wantMethod: "GET"}, 1697 12: {method: "GET", serverStatus: 303, wantMethod: "GET"}, 1698 13: {method: "GET", serverStatus: 307, wantMethod: "GET"}, 1699 14: {method: "GET", serverStatus: 308, wantMethod: "GET"}, 1700 1701 15: {method: "DELETE", serverStatus: 301, wantMethod: "GET"}, 1702 16: {method: "DELETE", serverStatus: 302, wantMethod: "GET"}, 1703 17: {method: "DELETE", serverStatus: 303, wantMethod: "GET"}, 1704 18: {method: "DELETE", serverStatus: 307, wantMethod: "DELETE"}, 1705 19: {method: "DELETE", serverStatus: 308, wantMethod: "DELETE"}, 1706 1707 20: {method: "PUT", serverStatus: 301, wantMethod: "GET"}, 1708 21: {method: "PUT", serverStatus: 302, wantMethod: "GET"}, 1709 22: {method: "PUT", serverStatus: 303, wantMethod: "GET"}, 1710 23: {method: "PUT", serverStatus: 307, wantMethod: "PUT"}, 1711 24: {method: "PUT", serverStatus: 308, wantMethod: "PUT"}, 1712 1713 25: {method: "MADEUPMETHOD", serverStatus: 301, wantMethod: "GET"}, 1714 26: {method: "MADEUPMETHOD", serverStatus: 302, wantMethod: "GET"}, 1715 27: {method: "MADEUPMETHOD", serverStatus: 303, wantMethod: "GET"}, 1716 28: {method: "MADEUPMETHOD", serverStatus: 307, wantMethod: "MADEUPMETHOD"}, 1717 29: {method: "MADEUPMETHOD", serverStatus: 308, wantMethod: "MADEUPMETHOD"}, 1718 } 1719 1720 handlerc := make(chan HandlerFunc, 1) 1721 1722 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { 1723 h := <-handlerc 1724 h(rw, req) 1725 })) 1726 defer ts.Close() 1727 1728 tr := &Transport{} 1729 defer tr.CloseIdleConnections() 1730 1731 for i, tt := range tests { 1732 handlerc <- func(w ResponseWriter, r *Request) { 1733 w.Header().Set("Location", ts.URL) 1734 w.WriteHeader(tt.serverStatus) 1735 } 1736 1737 req, err := NewRequest(tt.method, ts.URL, nil) 1738 if err != nil { 1739 t.Errorf("#%d: NewRequest: %v", i, err) 1740 continue 1741 } 1742 1743 c := &Client{Transport: tr} 1744 c.CheckRedirect = func(req *Request, via []*Request) error { 1745 if got, want := req.Method, tt.wantMethod; got != want { 1746 return fmt.Errorf("#%d: got next method %q; want %q", i, got, want) 1747 } 1748 handlerc <- func(rw ResponseWriter, req *Request) { 1749 // TODO: Check that the body is valid when we do 307 and 308 support 1750 } 1751 return nil 1752 } 1753 1754 res, err := c.Do(req) 1755 if err != nil { 1756 t.Errorf("#%d: Response: %v", i, err) 1757 continue 1758 } 1759 1760 res.Body.Close() 1761 } 1762 } 1763 1764 // issue18239Body is an io.ReadCloser for TestTransportBodyReadError. 1765 // Its Read returns readErr and increments *readCalls atomically. 1766 // Its Close returns nil and increments *closeCalls atomically. 1767 type issue18239Body struct { 1768 readCalls *int32 1769 closeCalls *int32 1770 readErr error 1771 } 1772 1773 func (b issue18239Body) Read([]byte) (int, error) { 1774 atomic.AddInt32(b.readCalls, 1) 1775 return 0, b.readErr 1776 } 1777 1778 func (b issue18239Body) Close() error { 1779 atomic.AddInt32(b.closeCalls, 1) 1780 return nil 1781 } 1782 1783 // Issue 18239: make sure the Transport doesn't retry requests with bodies. 1784 // (Especially if Request.GetBody is not defined.) 1785 func TestTransportBodyReadError(t *testing.T) { 1786 setParallel(t) 1787 defer afterTest(t) 1788 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { 1789 if r.URL.Path == "/ping" { 1790 return 1791 } 1792 buf := make([]byte, 1) 1793 n, err := r.Body.Read(buf) 1794 w.Header().Set("X-Body-Read", fmt.Sprintf("%v, %v", n, err)) 1795 })) 1796 defer ts.Close() 1797 tr := &Transport{} 1798 defer tr.CloseIdleConnections() 1799 c := &Client{Transport: tr} 1800 1801 // Do one initial successful request to create an idle TCP connection 1802 // for the subsequent request to reuse. (The Transport only retries 1803 // requests on reused connections.) 1804 res, err := c.Get(ts.URL + "/ping") 1805 if err != nil { 1806 t.Fatal(err) 1807 } 1808 res.Body.Close() 1809 1810 var readCallsAtomic int32 1811 var closeCallsAtomic int32 // atomic 1812 someErr := errors.New("some body read error") 1813 body := issue18239Body{&readCallsAtomic, &closeCallsAtomic, someErr} 1814 1815 req, err := NewRequest("POST", ts.URL, body) 1816 if err != nil { 1817 t.Fatal(err) 1818 } 1819 _, err = tr.RoundTrip(req) 1820 if err != someErr { 1821 t.Errorf("Got error: %v; want Request.Body read error: %v", err, someErr) 1822 } 1823 1824 // And verify that our Body wasn't used multiple times, which 1825 // would indicate retries. (as it buggily was during part of 1826 // Go 1.8's dev cycle) 1827 readCalls := atomic.LoadInt32(&readCallsAtomic) 1828 closeCalls := atomic.LoadInt32(&closeCallsAtomic) 1829 if readCalls != 1 { 1830 t.Errorf("read calls = %d; want 1", readCalls) 1831 } 1832 if closeCalls != 1 { 1833 t.Errorf("close calls = %d; want 1", closeCalls) 1834 } 1835 }