1// Copyright 2015 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 5package http2 6 7import ( 8 "bufio" 9 "bytes" 10 "context" 11 "crypto/tls" 12 "errors" 13 "flag" 14 "fmt" 15 "io" 16 "io/ioutil" 17 "log" 18 "math/rand" 19 "net" 20 "net/http" 21 "net/http/httptest" 22 "net/http/httptrace" 23 "net/textproto" 24 "net/url" 25 "os" 26 "reflect" 27 "runtime" 28 "sort" 29 "strconv" 30 "strings" 31 "sync" 32 "sync/atomic" 33 "testing" 34 "time" 35 36 "golang.org/x/net/http2/hpack" 37) 38 39var ( 40 extNet = flag.Bool("extnet", false, "do external network tests") 41 transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport") 42 insecure = flag.Bool("insecure", false, "insecure TLS dials") // TODO: dead code. remove? 43) 44 45var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true} 46 47var canceledCtx context.Context 48 49func init() { 50 ctx, cancel := context.WithCancel(context.Background()) 51 cancel() 52 canceledCtx = ctx 53} 54 55func TestTransportExternal(t *testing.T) { 56 if !*extNet { 57 t.Skip("skipping external network test") 58 } 59 req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil) 60 rt := &Transport{TLSClientConfig: tlsConfigInsecure} 61 res, err := rt.RoundTrip(req) 62 if err != nil { 63 t.Fatalf("%v", err) 64 } 65 res.Write(os.Stdout) 66} 67 68type fakeTLSConn struct { 69 net.Conn 70} 71 72func (c *fakeTLSConn) ConnectionState() tls.ConnectionState { 73 return tls.ConnectionState{ 74 Version: tls.VersionTLS12, 75 CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 76 } 77} 78 79func startH2cServer(t *testing.T) net.Listener { 80 h2Server := &Server{} 81 l := newLocalListener(t) 82 go func() { 83 conn, err := l.Accept() 84 if err != nil { 85 t.Error(err) 86 return 87 } 88 h2Server.ServeConn(&fakeTLSConn{conn}, &ServeConnOpts{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 89 fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil) 90 })}) 91 }() 92 return l 93} 94 95func TestTransportH2c(t *testing.T) { 96 l := startH2cServer(t) 97 defer l.Close() 98 req, err := http.NewRequest("GET", "http://"+l.Addr().String()+"/foobar", nil) 99 if err != nil { 100 t.Fatal(err) 101 } 102 var gotConnCnt int32 103 trace := &httptrace.ClientTrace{ 104 GotConn: func(connInfo httptrace.GotConnInfo) { 105 if !connInfo.Reused { 106 atomic.AddInt32(&gotConnCnt, 1) 107 } 108 }, 109 } 110 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) 111 tr := &Transport{ 112 AllowHTTP: true, 113 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { 114 return net.Dial(network, addr) 115 }, 116 } 117 res, err := tr.RoundTrip(req) 118 if err != nil { 119 t.Fatal(err) 120 } 121 if res.ProtoMajor != 2 { 122 t.Fatal("proto not h2c") 123 } 124 body, err := ioutil.ReadAll(res.Body) 125 if err != nil { 126 t.Fatal(err) 127 } 128 if got, want := string(body), "Hello, /foobar, http: true"; got != want { 129 t.Fatalf("response got %v, want %v", got, want) 130 } 131 if got, want := gotConnCnt, int32(1); got != want { 132 t.Errorf("Too many got connections: %d", gotConnCnt) 133 } 134} 135 136func TestTransport(t *testing.T) { 137 const body = "sup" 138 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 139 io.WriteString(w, body) 140 }, optOnlyServer) 141 defer st.Close() 142 143 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 144 defer tr.CloseIdleConnections() 145 146 u, err := url.Parse(st.ts.URL) 147 if err != nil { 148 t.Fatal(err) 149 } 150 for i, m := range []string{"GET", ""} { 151 req := &http.Request{ 152 Method: m, 153 URL: u, 154 } 155 res, err := tr.RoundTrip(req) 156 if err != nil { 157 t.Fatalf("%d: %s", i, err) 158 } 159 160 t.Logf("%d: Got res: %+v", i, res) 161 if g, w := res.StatusCode, 200; g != w { 162 t.Errorf("%d: StatusCode = %v; want %v", i, g, w) 163 } 164 if g, w := res.Status, "200 OK"; g != w { 165 t.Errorf("%d: Status = %q; want %q", i, g, w) 166 } 167 wantHeader := http.Header{ 168 "Content-Length": []string{"3"}, 169 "Content-Type": []string{"text/plain; charset=utf-8"}, 170 "Date": []string{"XXX"}, // see cleanDate 171 } 172 cleanDate(res) 173 if !reflect.DeepEqual(res.Header, wantHeader) { 174 t.Errorf("%d: res Header = %v; want %v", i, res.Header, wantHeader) 175 } 176 if res.Request != req { 177 t.Errorf("%d: Response.Request = %p; want %p", i, res.Request, req) 178 } 179 if res.TLS == nil { 180 t.Errorf("%d: Response.TLS = nil; want non-nil", i) 181 } 182 slurp, err := ioutil.ReadAll(res.Body) 183 if err != nil { 184 t.Errorf("%d: Body read: %v", i, err) 185 } else if string(slurp) != body { 186 t.Errorf("%d: Body = %q; want %q", i, slurp, body) 187 } 188 res.Body.Close() 189 } 190} 191 192func onSameConn(t *testing.T, modReq func(*http.Request)) bool { 193 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 194 io.WriteString(w, r.RemoteAddr) 195 }, optOnlyServer, func(c net.Conn, st http.ConnState) { 196 t.Logf("conn %v is now state %v", c.RemoteAddr(), st) 197 }) 198 defer st.Close() 199 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 200 defer tr.CloseIdleConnections() 201 get := func() string { 202 req, err := http.NewRequest("GET", st.ts.URL, nil) 203 if err != nil { 204 t.Fatal(err) 205 } 206 modReq(req) 207 res, err := tr.RoundTrip(req) 208 if err != nil { 209 t.Fatal(err) 210 } 211 defer res.Body.Close() 212 slurp, err := ioutil.ReadAll(res.Body) 213 if err != nil { 214 t.Fatalf("Body read: %v", err) 215 } 216 addr := strings.TrimSpace(string(slurp)) 217 if addr == "" { 218 t.Fatalf("didn't get an addr in response") 219 } 220 return addr 221 } 222 first := get() 223 second := get() 224 return first == second 225} 226 227func TestTransportReusesConns(t *testing.T) { 228 if !onSameConn(t, func(*http.Request) {}) { 229 t.Errorf("first and second responses were on different connections") 230 } 231} 232 233func TestTransportReusesConn_RequestClose(t *testing.T) { 234 if onSameConn(t, func(r *http.Request) { r.Close = true }) { 235 t.Errorf("first and second responses were not on different connections") 236 } 237} 238 239func TestTransportReusesConn_ConnClose(t *testing.T) { 240 if onSameConn(t, func(r *http.Request) { r.Header.Set("Connection", "close") }) { 241 t.Errorf("first and second responses were not on different connections") 242 } 243} 244 245// Tests that the Transport only keeps one pending dial open per destination address. 246// https://golang.org/issue/13397 247func TestTransportGroupsPendingDials(t *testing.T) { 248 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 249 io.WriteString(w, r.RemoteAddr) 250 }, optOnlyServer) 251 defer st.Close() 252 tr := &Transport{ 253 TLSClientConfig: tlsConfigInsecure, 254 } 255 defer tr.CloseIdleConnections() 256 var ( 257 mu sync.Mutex 258 dials = map[string]int{} 259 ) 260 var gotConnCnt int32 261 trace := &httptrace.ClientTrace{ 262 GotConn: func(connInfo httptrace.GotConnInfo) { 263 if !connInfo.Reused { 264 atomic.AddInt32(&gotConnCnt, 1) 265 } 266 }, 267 } 268 var wg sync.WaitGroup 269 for i := 0; i < 10; i++ { 270 wg.Add(1) 271 go func() { 272 defer wg.Done() 273 req, err := http.NewRequest("GET", st.ts.URL, nil) 274 if err != nil { 275 t.Error(err) 276 return 277 } 278 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) 279 res, err := tr.RoundTrip(req) 280 if err != nil { 281 t.Error(err) 282 return 283 } 284 defer res.Body.Close() 285 slurp, err := ioutil.ReadAll(res.Body) 286 if err != nil { 287 t.Errorf("Body read: %v", err) 288 } 289 addr := strings.TrimSpace(string(slurp)) 290 if addr == "" { 291 t.Errorf("didn't get an addr in response") 292 } 293 mu.Lock() 294 dials[addr]++ 295 mu.Unlock() 296 }() 297 } 298 wg.Wait() 299 if len(dials) != 1 { 300 t.Errorf("saw %d dials; want 1: %v", len(dials), dials) 301 } 302 tr.CloseIdleConnections() 303 if err := retry(50, 10*time.Millisecond, func() error { 304 cp, ok := tr.connPool().(*clientConnPool) 305 if !ok { 306 return fmt.Errorf("Conn pool is %T; want *clientConnPool", tr.connPool()) 307 } 308 cp.mu.Lock() 309 defer cp.mu.Unlock() 310 if len(cp.dialing) != 0 { 311 return fmt.Errorf("dialing map = %v; want empty", cp.dialing) 312 } 313 if len(cp.conns) != 0 { 314 return fmt.Errorf("conns = %v; want empty", cp.conns) 315 } 316 if len(cp.keys) != 0 { 317 return fmt.Errorf("keys = %v; want empty", cp.keys) 318 } 319 return nil 320 }); err != nil { 321 t.Errorf("State of pool after CloseIdleConnections: %v", err) 322 } 323 if got, want := gotConnCnt, int32(1); got != want { 324 t.Errorf("Too many got connections: %d", gotConnCnt) 325 } 326} 327 328func retry(tries int, delay time.Duration, fn func() error) error { 329 var err error 330 for i := 0; i < tries; i++ { 331 err = fn() 332 if err == nil { 333 return nil 334 } 335 time.Sleep(delay) 336 } 337 return err 338} 339 340func TestTransportAbortClosesPipes(t *testing.T) { 341 shutdown := make(chan struct{}) 342 st := newServerTester(t, 343 func(w http.ResponseWriter, r *http.Request) { 344 w.(http.Flusher).Flush() 345 <-shutdown 346 }, 347 optOnlyServer, 348 ) 349 defer st.Close() 350 defer close(shutdown) // we must shutdown before st.Close() to avoid hanging 351 352 errCh := make(chan error) 353 go func() { 354 defer close(errCh) 355 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 356 req, err := http.NewRequest("GET", st.ts.URL, nil) 357 if err != nil { 358 errCh <- err 359 return 360 } 361 res, err := tr.RoundTrip(req) 362 if err != nil { 363 errCh <- err 364 return 365 } 366 defer res.Body.Close() 367 st.closeConn() 368 _, err = ioutil.ReadAll(res.Body) 369 if err == nil { 370 errCh <- errors.New("expected error from res.Body.Read") 371 return 372 } 373 }() 374 375 select { 376 case err := <-errCh: 377 if err != nil { 378 t.Fatal(err) 379 } 380 // deadlock? that's a bug. 381 case <-time.After(3 * time.Second): 382 t.Fatal("timeout") 383 } 384} 385 386// TODO: merge this with TestTransportBody to make TestTransportRequest? This 387// could be a table-driven test with extra goodies. 388func TestTransportPath(t *testing.T) { 389 gotc := make(chan *url.URL, 1) 390 st := newServerTester(t, 391 func(w http.ResponseWriter, r *http.Request) { 392 gotc <- r.URL 393 }, 394 optOnlyServer, 395 ) 396 defer st.Close() 397 398 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 399 defer tr.CloseIdleConnections() 400 const ( 401 path = "/testpath" 402 query = "q=1" 403 ) 404 surl := st.ts.URL + path + "?" + query 405 req, err := http.NewRequest("POST", surl, nil) 406 if err != nil { 407 t.Fatal(err) 408 } 409 c := &http.Client{Transport: tr} 410 res, err := c.Do(req) 411 if err != nil { 412 t.Fatal(err) 413 } 414 defer res.Body.Close() 415 got := <-gotc 416 if got.Path != path { 417 t.Errorf("Read Path = %q; want %q", got.Path, path) 418 } 419 if got.RawQuery != query { 420 t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query) 421 } 422} 423 424func randString(n int) string { 425 rnd := rand.New(rand.NewSource(int64(n))) 426 b := make([]byte, n) 427 for i := range b { 428 b[i] = byte(rnd.Intn(256)) 429 } 430 return string(b) 431} 432 433type panicReader struct{} 434 435func (panicReader) Read([]byte) (int, error) { panic("unexpected Read") } 436func (panicReader) Close() error { panic("unexpected Close") } 437 438func TestActualContentLength(t *testing.T) { 439 tests := []struct { 440 req *http.Request 441 want int64 442 }{ 443 // Verify we don't read from Body: 444 0: { 445 req: &http.Request{Body: panicReader{}}, 446 want: -1, 447 }, 448 // nil Body means 0, regardless of ContentLength: 449 1: { 450 req: &http.Request{Body: nil, ContentLength: 5}, 451 want: 0, 452 }, 453 // ContentLength is used if set. 454 2: { 455 req: &http.Request{Body: panicReader{}, ContentLength: 5}, 456 want: 5, 457 }, 458 // http.NoBody means 0, not -1. 459 3: { 460 req: &http.Request{Body: http.NoBody}, 461 want: 0, 462 }, 463 } 464 for i, tt := range tests { 465 got := actualContentLength(tt.req) 466 if got != tt.want { 467 t.Errorf("test[%d]: got %d; want %d", i, got, tt.want) 468 } 469 } 470} 471 472func TestTransportBody(t *testing.T) { 473 bodyTests := []struct { 474 body string 475 noContentLen bool 476 }{ 477 {body: "some message"}, 478 {body: "some message", noContentLen: true}, 479 {body: strings.Repeat("a", 1<<20), noContentLen: true}, 480 {body: strings.Repeat("a", 1<<20)}, 481 {body: randString(16<<10 - 1)}, 482 {body: randString(16 << 10)}, 483 {body: randString(16<<10 + 1)}, 484 {body: randString(512<<10 - 1)}, 485 {body: randString(512 << 10)}, 486 {body: randString(512<<10 + 1)}, 487 {body: randString(1<<20 - 1)}, 488 {body: randString(1 << 20)}, 489 {body: randString(1<<20 + 2)}, 490 } 491 492 type reqInfo struct { 493 req *http.Request 494 slurp []byte 495 err error 496 } 497 gotc := make(chan reqInfo, 1) 498 st := newServerTester(t, 499 func(w http.ResponseWriter, r *http.Request) { 500 slurp, err := ioutil.ReadAll(r.Body) 501 if err != nil { 502 gotc <- reqInfo{err: err} 503 } else { 504 gotc <- reqInfo{req: r, slurp: slurp} 505 } 506 }, 507 optOnlyServer, 508 ) 509 defer st.Close() 510 511 for i, tt := range bodyTests { 512 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 513 defer tr.CloseIdleConnections() 514 515 var body io.Reader = strings.NewReader(tt.body) 516 if tt.noContentLen { 517 body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods 518 } 519 req, err := http.NewRequest("POST", st.ts.URL, body) 520 if err != nil { 521 t.Fatalf("#%d: %v", i, err) 522 } 523 c := &http.Client{Transport: tr} 524 res, err := c.Do(req) 525 if err != nil { 526 t.Fatalf("#%d: %v", i, err) 527 } 528 defer res.Body.Close() 529 ri := <-gotc 530 if ri.err != nil { 531 t.Errorf("#%d: read error: %v", i, ri.err) 532 continue 533 } 534 if got := string(ri.slurp); got != tt.body { 535 t.Errorf("#%d: Read body mismatch.\n got: %q (len %d)\nwant: %q (len %d)", i, shortString(got), len(got), shortString(tt.body), len(tt.body)) 536 } 537 wantLen := int64(len(tt.body)) 538 if tt.noContentLen && tt.body != "" { 539 wantLen = -1 540 } 541 if ri.req.ContentLength != wantLen { 542 t.Errorf("#%d. handler got ContentLength = %v; want %v", i, ri.req.ContentLength, wantLen) 543 } 544 } 545} 546 547func shortString(v string) string { 548 const maxLen = 100 549 if len(v) <= maxLen { 550 return v 551 } 552 return fmt.Sprintf("%v[...%d bytes omitted...]%v", v[:maxLen/2], len(v)-maxLen, v[len(v)-maxLen/2:]) 553} 554 555func TestTransportDialTLS(t *testing.T) { 556 var mu sync.Mutex // guards following 557 var gotReq, didDial bool 558 559 ts := newServerTester(t, 560 func(w http.ResponseWriter, r *http.Request) { 561 mu.Lock() 562 gotReq = true 563 mu.Unlock() 564 }, 565 optOnlyServer, 566 ) 567 defer ts.Close() 568 tr := &Transport{ 569 DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) { 570 mu.Lock() 571 didDial = true 572 mu.Unlock() 573 cfg.InsecureSkipVerify = true 574 c, err := tls.Dial(netw, addr, cfg) 575 if err != nil { 576 return nil, err 577 } 578 return c, c.Handshake() 579 }, 580 } 581 defer tr.CloseIdleConnections() 582 client := &http.Client{Transport: tr} 583 res, err := client.Get(ts.ts.URL) 584 if err != nil { 585 t.Fatal(err) 586 } 587 res.Body.Close() 588 mu.Lock() 589 if !gotReq { 590 t.Error("didn't get request") 591 } 592 if !didDial { 593 t.Error("didn't use dial hook") 594 } 595} 596 597func TestConfigureTransport(t *testing.T) { 598 t1 := &http.Transport{} 599 err := ConfigureTransport(t1) 600 if err != nil { 601 t.Fatal(err) 602 } 603 if got := fmt.Sprintf("%#v", t1); !strings.Contains(got, `"h2"`) { 604 // Laziness, to avoid buildtags. 605 t.Errorf("stringification of HTTP/1 transport didn't contain \"h2\": %v", got) 606 } 607 wantNextProtos := []string{"h2", "http/1.1"} 608 if t1.TLSClientConfig == nil { 609 t.Errorf("nil t1.TLSClientConfig") 610 } else if !reflect.DeepEqual(t1.TLSClientConfig.NextProtos, wantNextProtos) { 611 t.Errorf("TLSClientConfig.NextProtos = %q; want %q", t1.TLSClientConfig.NextProtos, wantNextProtos) 612 } 613 if err := ConfigureTransport(t1); err == nil { 614 t.Error("unexpected success on second call to ConfigureTransport") 615 } 616 617 // And does it work? 618 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 619 io.WriteString(w, r.Proto) 620 }, optOnlyServer) 621 defer st.Close() 622 623 t1.TLSClientConfig.InsecureSkipVerify = true 624 c := &http.Client{Transport: t1} 625 res, err := c.Get(st.ts.URL) 626 if err != nil { 627 t.Fatal(err) 628 } 629 slurp, err := ioutil.ReadAll(res.Body) 630 if err != nil { 631 t.Fatal(err) 632 } 633 if got, want := string(slurp), "HTTP/2.0"; got != want { 634 t.Errorf("body = %q; want %q", got, want) 635 } 636} 637 638type capitalizeReader struct { 639 r io.Reader 640} 641 642func (cr capitalizeReader) Read(p []byte) (n int, err error) { 643 n, err = cr.r.Read(p) 644 for i, b := range p[:n] { 645 if b >= 'a' && b <= 'z' { 646 p[i] = b - ('a' - 'A') 647 } 648 } 649 return 650} 651 652type flushWriter struct { 653 w io.Writer 654} 655 656func (fw flushWriter) Write(p []byte) (n int, err error) { 657 n, err = fw.w.Write(p) 658 if f, ok := fw.w.(http.Flusher); ok { 659 f.Flush() 660 } 661 return 662} 663 664type clientTester struct { 665 t *testing.T 666 tr *Transport 667 sc, cc net.Conn // server and client conn 668 fr *Framer // server's framer 669 client func() error 670 server func() error 671} 672 673func newClientTester(t *testing.T) *clientTester { 674 var dialOnce struct { 675 sync.Mutex 676 dialed bool 677 } 678 ct := &clientTester{ 679 t: t, 680 } 681 ct.tr = &Transport{ 682 TLSClientConfig: tlsConfigInsecure, 683 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { 684 dialOnce.Lock() 685 defer dialOnce.Unlock() 686 if dialOnce.dialed { 687 return nil, errors.New("only one dial allowed in test mode") 688 } 689 dialOnce.dialed = true 690 return ct.cc, nil 691 }, 692 } 693 694 ln := newLocalListener(t) 695 cc, err := net.Dial("tcp", ln.Addr().String()) 696 if err != nil { 697 t.Fatal(err) 698 699 } 700 sc, err := ln.Accept() 701 if err != nil { 702 t.Fatal(err) 703 } 704 ln.Close() 705 ct.cc = cc 706 ct.sc = sc 707 ct.fr = NewFramer(sc, sc) 708 return ct 709} 710 711func newLocalListener(t *testing.T) net.Listener { 712 ln, err := net.Listen("tcp4", "127.0.0.1:0") 713 if err == nil { 714 return ln 715 } 716 ln, err = net.Listen("tcp6", "[::1]:0") 717 if err != nil { 718 t.Fatal(err) 719 } 720 return ln 721} 722 723func (ct *clientTester) greet(settings ...Setting) { 724 buf := make([]byte, len(ClientPreface)) 725 _, err := io.ReadFull(ct.sc, buf) 726 if err != nil { 727 ct.t.Fatalf("reading client preface: %v", err) 728 } 729 f, err := ct.fr.ReadFrame() 730 if err != nil { 731 ct.t.Fatalf("Reading client settings frame: %v", err) 732 } 733 if sf, ok := f.(*SettingsFrame); !ok { 734 ct.t.Fatalf("Wanted client settings frame; got %v", f) 735 _ = sf // stash it away? 736 } 737 if err := ct.fr.WriteSettings(settings...); err != nil { 738 ct.t.Fatal(err) 739 } 740 if err := ct.fr.WriteSettingsAck(); err != nil { 741 ct.t.Fatal(err) 742 } 743} 744 745func (ct *clientTester) readNonSettingsFrame() (Frame, error) { 746 for { 747 f, err := ct.fr.ReadFrame() 748 if err != nil { 749 return nil, err 750 } 751 if _, ok := f.(*SettingsFrame); ok { 752 continue 753 } 754 return f, nil 755 } 756} 757 758func (ct *clientTester) cleanup() { 759 ct.tr.CloseIdleConnections() 760 761 // close both connections, ignore the error if its already closed 762 ct.sc.Close() 763 ct.cc.Close() 764} 765 766func (ct *clientTester) run() { 767 var errOnce sync.Once 768 var wg sync.WaitGroup 769 770 run := func(which string, fn func() error) { 771 defer wg.Done() 772 if err := fn(); err != nil { 773 errOnce.Do(func() { 774 ct.t.Errorf("%s: %v", which, err) 775 ct.cleanup() 776 }) 777 } 778 } 779 780 wg.Add(2) 781 go run("client", ct.client) 782 go run("server", ct.server) 783 wg.Wait() 784 785 errOnce.Do(ct.cleanup) // clean up if no error 786} 787 788func (ct *clientTester) readFrame() (Frame, error) { 789 return readFrameTimeout(ct.fr, 2*time.Second) 790} 791 792func (ct *clientTester) firstHeaders() (*HeadersFrame, error) { 793 for { 794 f, err := ct.readFrame() 795 if err != nil { 796 return nil, fmt.Errorf("ReadFrame while waiting for Headers: %v", err) 797 } 798 switch f.(type) { 799 case *WindowUpdateFrame, *SettingsFrame: 800 continue 801 } 802 hf, ok := f.(*HeadersFrame) 803 if !ok { 804 return nil, fmt.Errorf("Got %T; want HeadersFrame", f) 805 } 806 return hf, nil 807 } 808} 809 810type countingReader struct { 811 n *int64 812} 813 814func (r countingReader) Read(p []byte) (n int, err error) { 815 for i := range p { 816 p[i] = byte(i) 817 } 818 atomic.AddInt64(r.n, int64(len(p))) 819 return len(p), err 820} 821 822func TestTransportReqBodyAfterResponse_200(t *testing.T) { testTransportReqBodyAfterResponse(t, 200) } 823func TestTransportReqBodyAfterResponse_403(t *testing.T) { testTransportReqBodyAfterResponse(t, 403) } 824 825func testTransportReqBodyAfterResponse(t *testing.T, status int) { 826 const bodySize = 10 << 20 827 clientDone := make(chan struct{}) 828 ct := newClientTester(t) 829 ct.client = func() error { 830 defer ct.cc.(*net.TCPConn).CloseWrite() 831 if runtime.GOOS == "plan9" { 832 // CloseWrite not supported on Plan 9; Issue 17906 833 defer ct.cc.(*net.TCPConn).Close() 834 } 835 defer close(clientDone) 836 837 var n int64 // atomic 838 req, err := http.NewRequest("PUT", "https://dummy.tld/", io.LimitReader(countingReader{&n}, bodySize)) 839 if err != nil { 840 return err 841 } 842 res, err := ct.tr.RoundTrip(req) 843 if err != nil { 844 return fmt.Errorf("RoundTrip: %v", err) 845 } 846 defer res.Body.Close() 847 if res.StatusCode != status { 848 return fmt.Errorf("status code = %v; want %v", res.StatusCode, status) 849 } 850 slurp, err := ioutil.ReadAll(res.Body) 851 if err != nil { 852 return fmt.Errorf("Slurp: %v", err) 853 } 854 if len(slurp) > 0 { 855 return fmt.Errorf("unexpected body: %q", slurp) 856 } 857 if status == 200 { 858 if got := atomic.LoadInt64(&n); got != bodySize { 859 return fmt.Errorf("For 200 response, Transport wrote %d bytes; want %d", got, bodySize) 860 } 861 } else { 862 if got := atomic.LoadInt64(&n); got == 0 || got >= bodySize { 863 return fmt.Errorf("For %d response, Transport wrote %d bytes; want (0,%d) exclusive", status, got, bodySize) 864 } 865 } 866 return nil 867 } 868 ct.server = func() error { 869 ct.greet() 870 var buf bytes.Buffer 871 enc := hpack.NewEncoder(&buf) 872 var dataRecv int64 873 var closed bool 874 for { 875 f, err := ct.fr.ReadFrame() 876 if err != nil { 877 select { 878 case <-clientDone: 879 // If the client's done, it 880 // will have reported any 881 // errors on its side. 882 return nil 883 default: 884 return err 885 } 886 } 887 //println(fmt.Sprintf("server got frame: %v", f)) 888 switch f := f.(type) { 889 case *WindowUpdateFrame, *SettingsFrame: 890 case *HeadersFrame: 891 if !f.HeadersEnded() { 892 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) 893 } 894 if f.StreamEnded() { 895 return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f) 896 } 897 case *DataFrame: 898 dataLen := len(f.Data()) 899 if dataLen > 0 { 900 if dataRecv == 0 { 901 enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)}) 902 ct.fr.WriteHeaders(HeadersFrameParam{ 903 StreamID: f.StreamID, 904 EndHeaders: true, 905 EndStream: false, 906 BlockFragment: buf.Bytes(), 907 }) 908 } 909 if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil { 910 return err 911 } 912 if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil { 913 return err 914 } 915 } 916 dataRecv += int64(dataLen) 917 918 if !closed && ((status != 200 && dataRecv > 0) || 919 (status == 200 && dataRecv == bodySize)) { 920 closed = true 921 if err := ct.fr.WriteData(f.StreamID, true, nil); err != nil { 922 return err 923 } 924 } 925 default: 926 return fmt.Errorf("Unexpected client frame %v", f) 927 } 928 } 929 } 930 ct.run() 931} 932 933// See golang.org/issue/13444 934func TestTransportFullDuplex(t *testing.T) { 935 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 936 w.WriteHeader(200) // redundant but for clarity 937 w.(http.Flusher).Flush() 938 io.Copy(flushWriter{w}, capitalizeReader{r.Body}) 939 fmt.Fprintf(w, "bye.\n") 940 }, optOnlyServer) 941 defer st.Close() 942 943 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 944 defer tr.CloseIdleConnections() 945 c := &http.Client{Transport: tr} 946 947 pr, pw := io.Pipe() 948 req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr)) 949 if err != nil { 950 t.Fatal(err) 951 } 952 req.ContentLength = -1 953 res, err := c.Do(req) 954 if err != nil { 955 t.Fatal(err) 956 } 957 defer res.Body.Close() 958 if res.StatusCode != 200 { 959 t.Fatalf("StatusCode = %v; want %v", res.StatusCode, 200) 960 } 961 bs := bufio.NewScanner(res.Body) 962 want := func(v string) { 963 if !bs.Scan() { 964 t.Fatalf("wanted to read %q but Scan() = false, err = %v", v, bs.Err()) 965 } 966 } 967 write := func(v string) { 968 _, err := io.WriteString(pw, v) 969 if err != nil { 970 t.Fatalf("pipe write: %v", err) 971 } 972 } 973 write("foo\n") 974 want("FOO") 975 write("bar\n") 976 want("BAR") 977 pw.Close() 978 want("bye.") 979 if err := bs.Err(); err != nil { 980 t.Fatal(err) 981 } 982} 983 984func TestTransportConnectRequest(t *testing.T) { 985 gotc := make(chan *http.Request, 1) 986 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 987 gotc <- r 988 }, optOnlyServer) 989 defer st.Close() 990 991 u, err := url.Parse(st.ts.URL) 992 if err != nil { 993 t.Fatal(err) 994 } 995 996 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 997 defer tr.CloseIdleConnections() 998 c := &http.Client{Transport: tr} 999 1000 tests := []struct { 1001 req *http.Request 1002 want string 1003 }{ 1004 { 1005 req: &http.Request{ 1006 Method: "CONNECT", 1007 Header: http.Header{}, 1008 URL: u, 1009 }, 1010 want: u.Host, 1011 }, 1012 { 1013 req: &http.Request{ 1014 Method: "CONNECT", 1015 Header: http.Header{}, 1016 URL: u, 1017 Host: "example.com:123", 1018 }, 1019 want: "example.com:123", 1020 }, 1021 } 1022 1023 for i, tt := range tests { 1024 res, err := c.Do(tt.req) 1025 if err != nil { 1026 t.Errorf("%d. RoundTrip = %v", i, err) 1027 continue 1028 } 1029 res.Body.Close() 1030 req := <-gotc 1031 if req.Method != "CONNECT" { 1032 t.Errorf("method = %q; want CONNECT", req.Method) 1033 } 1034 if req.Host != tt.want { 1035 t.Errorf("Host = %q; want %q", req.Host, tt.want) 1036 } 1037 if req.URL.Host != tt.want { 1038 t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want) 1039 } 1040 } 1041} 1042 1043type headerType int 1044 1045const ( 1046 noHeader headerType = iota // omitted 1047 oneHeader 1048 splitHeader // broken into continuation on purpose 1049) 1050 1051const ( 1052 f0 = noHeader 1053 f1 = oneHeader 1054 f2 = splitHeader 1055 d0 = false 1056 d1 = true 1057) 1058 1059// Test all 36 combinations of response frame orders: 1060// (3 ways of 100-continue) * (2 ways of headers) * (2 ways of data) * (3 ways of trailers):func TestTransportResponsePattern_00f0(t *testing.T) { testTransportResponsePattern(h0, h1, false, h0) } 1061// Generated by http://play.golang.org/p/SScqYKJYXd 1062func TestTransportResPattern_c0h1d0t0(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f0) } 1063func TestTransportResPattern_c0h1d0t1(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f1) } 1064func TestTransportResPattern_c0h1d0t2(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f2) } 1065func TestTransportResPattern_c0h1d1t0(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f0) } 1066func TestTransportResPattern_c0h1d1t1(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f1) } 1067func TestTransportResPattern_c0h1d1t2(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f2) } 1068func TestTransportResPattern_c0h2d0t0(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f0) } 1069func TestTransportResPattern_c0h2d0t1(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f1) } 1070func TestTransportResPattern_c0h2d0t2(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f2) } 1071func TestTransportResPattern_c0h2d1t0(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f0) } 1072func TestTransportResPattern_c0h2d1t1(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f1) } 1073func TestTransportResPattern_c0h2d1t2(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f2) } 1074func TestTransportResPattern_c1h1d0t0(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f0) } 1075func TestTransportResPattern_c1h1d0t1(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f1) } 1076func TestTransportResPattern_c1h1d0t2(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f2) } 1077func TestTransportResPattern_c1h1d1t0(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f0) } 1078func TestTransportResPattern_c1h1d1t1(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f1) } 1079func TestTransportResPattern_c1h1d1t2(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f2) } 1080func TestTransportResPattern_c1h2d0t0(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f0) } 1081func TestTransportResPattern_c1h2d0t1(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f1) } 1082func TestTransportResPattern_c1h2d0t2(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f2) } 1083func TestTransportResPattern_c1h2d1t0(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f0) } 1084func TestTransportResPattern_c1h2d1t1(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f1) } 1085func TestTransportResPattern_c1h2d1t2(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f2) } 1086func TestTransportResPattern_c2h1d0t0(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f0) } 1087func TestTransportResPattern_c2h1d0t1(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f1) } 1088func TestTransportResPattern_c2h1d0t2(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f2) } 1089func TestTransportResPattern_c2h1d1t0(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f0) } 1090func TestTransportResPattern_c2h1d1t1(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f1) } 1091func TestTransportResPattern_c2h1d1t2(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f2) } 1092func TestTransportResPattern_c2h2d0t0(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f0) } 1093func TestTransportResPattern_c2h2d0t1(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f1) } 1094func TestTransportResPattern_c2h2d0t2(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f2) } 1095func TestTransportResPattern_c2h2d1t0(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f0) } 1096func TestTransportResPattern_c2h2d1t1(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f1) } 1097func TestTransportResPattern_c2h2d1t2(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f2) } 1098 1099func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerType, withData bool, trailers headerType) { 1100 const reqBody = "some request body" 1101 const resBody = "some response body" 1102 1103 if resHeader == noHeader { 1104 // TODO: test 100-continue followed by immediate 1105 // server stream reset, without headers in the middle? 1106 panic("invalid combination") 1107 } 1108 1109 ct := newClientTester(t) 1110 ct.client = func() error { 1111 req, _ := http.NewRequest("POST", "https://dummy.tld/", strings.NewReader(reqBody)) 1112 if expect100Continue != noHeader { 1113 req.Header.Set("Expect", "100-continue") 1114 } 1115 res, err := ct.tr.RoundTrip(req) 1116 if err != nil { 1117 return fmt.Errorf("RoundTrip: %v", err) 1118 } 1119 defer res.Body.Close() 1120 if res.StatusCode != 200 { 1121 return fmt.Errorf("status code = %v; want 200", res.StatusCode) 1122 } 1123 slurp, err := ioutil.ReadAll(res.Body) 1124 if err != nil { 1125 return fmt.Errorf("Slurp: %v", err) 1126 } 1127 wantBody := resBody 1128 if !withData { 1129 wantBody = "" 1130 } 1131 if string(slurp) != wantBody { 1132 return fmt.Errorf("body = %q; want %q", slurp, wantBody) 1133 } 1134 if trailers == noHeader { 1135 if len(res.Trailer) > 0 { 1136 t.Errorf("Trailer = %v; want none", res.Trailer) 1137 } 1138 } else { 1139 want := http.Header{"Some-Trailer": {"some-value"}} 1140 if !reflect.DeepEqual(res.Trailer, want) { 1141 t.Errorf("Trailer = %v; want %v", res.Trailer, want) 1142 } 1143 } 1144 return nil 1145 } 1146 ct.server = func() error { 1147 ct.greet() 1148 var buf bytes.Buffer 1149 enc := hpack.NewEncoder(&buf) 1150 1151 for { 1152 f, err := ct.fr.ReadFrame() 1153 if err != nil { 1154 return err 1155 } 1156 endStream := false 1157 send := func(mode headerType) { 1158 hbf := buf.Bytes() 1159 switch mode { 1160 case oneHeader: 1161 ct.fr.WriteHeaders(HeadersFrameParam{ 1162 StreamID: f.Header().StreamID, 1163 EndHeaders: true, 1164 EndStream: endStream, 1165 BlockFragment: hbf, 1166 }) 1167 case splitHeader: 1168 if len(hbf) < 2 { 1169 panic("too small") 1170 } 1171 ct.fr.WriteHeaders(HeadersFrameParam{ 1172 StreamID: f.Header().StreamID, 1173 EndHeaders: false, 1174 EndStream: endStream, 1175 BlockFragment: hbf[:1], 1176 }) 1177 ct.fr.WriteContinuation(f.Header().StreamID, true, hbf[1:]) 1178 default: 1179 panic("bogus mode") 1180 } 1181 } 1182 switch f := f.(type) { 1183 case *WindowUpdateFrame, *SettingsFrame: 1184 case *DataFrame: 1185 if !f.StreamEnded() { 1186 // No need to send flow control tokens. The test request body is tiny. 1187 continue 1188 } 1189 // Response headers (1+ frames; 1 or 2 in this test, but never 0) 1190 { 1191 buf.Reset() 1192 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 1193 enc.WriteField(hpack.HeaderField{Name: "x-foo", Value: "blah"}) 1194 enc.WriteField(hpack.HeaderField{Name: "x-bar", Value: "more"}) 1195 if trailers != noHeader { 1196 enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "some-trailer"}) 1197 } 1198 endStream = withData == false && trailers == noHeader 1199 send(resHeader) 1200 } 1201 if withData { 1202 endStream = trailers == noHeader 1203 ct.fr.WriteData(f.StreamID, endStream, []byte(resBody)) 1204 } 1205 if trailers != noHeader { 1206 endStream = true 1207 buf.Reset() 1208 enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "some-value"}) 1209 send(trailers) 1210 } 1211 if endStream { 1212 return nil 1213 } 1214 case *HeadersFrame: 1215 if expect100Continue != noHeader { 1216 buf.Reset() 1217 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"}) 1218 send(expect100Continue) 1219 } 1220 } 1221 } 1222 } 1223 ct.run() 1224} 1225 1226// Issue 26189, Issue 17739: ignore unknown 1xx responses 1227func TestTransportUnknown1xx(t *testing.T) { 1228 var buf bytes.Buffer 1229 defer func() { got1xxFuncForTests = nil }() 1230 got1xxFuncForTests = func(code int, header textproto.MIMEHeader) error { 1231 fmt.Fprintf(&buf, "code=%d header=%v\n", code, header) 1232 return nil 1233 } 1234 1235 ct := newClientTester(t) 1236 ct.client = func() error { 1237 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 1238 res, err := ct.tr.RoundTrip(req) 1239 if err != nil { 1240 return fmt.Errorf("RoundTrip: %v", err) 1241 } 1242 defer res.Body.Close() 1243 if res.StatusCode != 204 { 1244 return fmt.Errorf("status code = %v; want 204", res.StatusCode) 1245 } 1246 want := `code=110 header=map[Foo-Bar:[110]] 1247code=111 header=map[Foo-Bar:[111]] 1248code=112 header=map[Foo-Bar:[112]] 1249code=113 header=map[Foo-Bar:[113]] 1250code=114 header=map[Foo-Bar:[114]] 1251` 1252 if got := buf.String(); got != want { 1253 t.Errorf("Got trace:\n%s\nWant:\n%s", got, want) 1254 } 1255 return nil 1256 } 1257 ct.server = func() error { 1258 ct.greet() 1259 var buf bytes.Buffer 1260 enc := hpack.NewEncoder(&buf) 1261 1262 for { 1263 f, err := ct.fr.ReadFrame() 1264 if err != nil { 1265 return err 1266 } 1267 switch f := f.(type) { 1268 case *WindowUpdateFrame, *SettingsFrame: 1269 case *HeadersFrame: 1270 for i := 110; i <= 114; i++ { 1271 buf.Reset() 1272 enc.WriteField(hpack.HeaderField{Name: ":status", Value: fmt.Sprint(i)}) 1273 enc.WriteField(hpack.HeaderField{Name: "foo-bar", Value: fmt.Sprint(i)}) 1274 ct.fr.WriteHeaders(HeadersFrameParam{ 1275 StreamID: f.StreamID, 1276 EndHeaders: true, 1277 EndStream: false, 1278 BlockFragment: buf.Bytes(), 1279 }) 1280 } 1281 buf.Reset() 1282 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) 1283 ct.fr.WriteHeaders(HeadersFrameParam{ 1284 StreamID: f.StreamID, 1285 EndHeaders: true, 1286 EndStream: false, 1287 BlockFragment: buf.Bytes(), 1288 }) 1289 return nil 1290 } 1291 } 1292 } 1293 ct.run() 1294 1295} 1296 1297func TestTransportReceiveUndeclaredTrailer(t *testing.T) { 1298 ct := newClientTester(t) 1299 ct.client = func() error { 1300 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 1301 res, err := ct.tr.RoundTrip(req) 1302 if err != nil { 1303 return fmt.Errorf("RoundTrip: %v", err) 1304 } 1305 defer res.Body.Close() 1306 if res.StatusCode != 200 { 1307 return fmt.Errorf("status code = %v; want 200", res.StatusCode) 1308 } 1309 slurp, err := ioutil.ReadAll(res.Body) 1310 if err != nil { 1311 return fmt.Errorf("res.Body ReadAll error = %q, %v; want %v", slurp, err, nil) 1312 } 1313 if len(slurp) > 0 { 1314 return fmt.Errorf("body = %q; want nothing", slurp) 1315 } 1316 if _, ok := res.Trailer["Some-Trailer"]; !ok { 1317 return fmt.Errorf("expected Some-Trailer") 1318 } 1319 return nil 1320 } 1321 ct.server = func() error { 1322 ct.greet() 1323 1324 var n int 1325 var hf *HeadersFrame 1326 for hf == nil && n < 10 { 1327 f, err := ct.fr.ReadFrame() 1328 if err != nil { 1329 return err 1330 } 1331 hf, _ = f.(*HeadersFrame) 1332 n++ 1333 } 1334 1335 var buf bytes.Buffer 1336 enc := hpack.NewEncoder(&buf) 1337 1338 // send headers without Trailer header 1339 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 1340 ct.fr.WriteHeaders(HeadersFrameParam{ 1341 StreamID: hf.StreamID, 1342 EndHeaders: true, 1343 EndStream: false, 1344 BlockFragment: buf.Bytes(), 1345 }) 1346 1347 // send trailers 1348 buf.Reset() 1349 enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "I'm an undeclared Trailer!"}) 1350 ct.fr.WriteHeaders(HeadersFrameParam{ 1351 StreamID: hf.StreamID, 1352 EndHeaders: true, 1353 EndStream: true, 1354 BlockFragment: buf.Bytes(), 1355 }) 1356 return nil 1357 } 1358 ct.run() 1359} 1360 1361func TestTransportInvalidTrailer_Pseudo1(t *testing.T) { 1362 testTransportInvalidTrailer_Pseudo(t, oneHeader) 1363} 1364func TestTransportInvalidTrailer_Pseudo2(t *testing.T) { 1365 testTransportInvalidTrailer_Pseudo(t, splitHeader) 1366} 1367func testTransportInvalidTrailer_Pseudo(t *testing.T, trailers headerType) { 1368 testInvalidTrailer(t, trailers, pseudoHeaderError(":colon"), func(enc *hpack.Encoder) { 1369 enc.WriteField(hpack.HeaderField{Name: ":colon", Value: "foo"}) 1370 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) 1371 }) 1372} 1373 1374func TestTransportInvalidTrailer_Capital1(t *testing.T) { 1375 testTransportInvalidTrailer_Capital(t, oneHeader) 1376} 1377func TestTransportInvalidTrailer_Capital2(t *testing.T) { 1378 testTransportInvalidTrailer_Capital(t, splitHeader) 1379} 1380func testTransportInvalidTrailer_Capital(t *testing.T, trailers headerType) { 1381 testInvalidTrailer(t, trailers, headerFieldNameError("Capital"), func(enc *hpack.Encoder) { 1382 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) 1383 enc.WriteField(hpack.HeaderField{Name: "Capital", Value: "bad"}) 1384 }) 1385} 1386func TestTransportInvalidTrailer_EmptyFieldName(t *testing.T) { 1387 testInvalidTrailer(t, oneHeader, headerFieldNameError(""), func(enc *hpack.Encoder) { 1388 enc.WriteField(hpack.HeaderField{Name: "", Value: "bad"}) 1389 }) 1390} 1391func TestTransportInvalidTrailer_BinaryFieldValue(t *testing.T) { 1392 testInvalidTrailer(t, oneHeader, headerFieldValueError("has\nnewline"), func(enc *hpack.Encoder) { 1393 enc.WriteField(hpack.HeaderField{Name: "x", Value: "has\nnewline"}) 1394 }) 1395} 1396 1397func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeTrailer func(*hpack.Encoder)) { 1398 ct := newClientTester(t) 1399 ct.client = func() error { 1400 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 1401 res, err := ct.tr.RoundTrip(req) 1402 if err != nil { 1403 return fmt.Errorf("RoundTrip: %v", err) 1404 } 1405 defer res.Body.Close() 1406 if res.StatusCode != 200 { 1407 return fmt.Errorf("status code = %v; want 200", res.StatusCode) 1408 } 1409 slurp, err := ioutil.ReadAll(res.Body) 1410 se, ok := err.(StreamError) 1411 if !ok || se.Cause != wantErr { 1412 return fmt.Errorf("res.Body ReadAll error = %q, %#v; want StreamError with cause %T, %#v", slurp, err, wantErr, wantErr) 1413 } 1414 if len(slurp) > 0 { 1415 return fmt.Errorf("body = %q; want nothing", slurp) 1416 } 1417 return nil 1418 } 1419 ct.server = func() error { 1420 ct.greet() 1421 var buf bytes.Buffer 1422 enc := hpack.NewEncoder(&buf) 1423 1424 for { 1425 f, err := ct.fr.ReadFrame() 1426 if err != nil { 1427 return err 1428 } 1429 switch f := f.(type) { 1430 case *HeadersFrame: 1431 var endStream bool 1432 send := func(mode headerType) { 1433 hbf := buf.Bytes() 1434 switch mode { 1435 case oneHeader: 1436 ct.fr.WriteHeaders(HeadersFrameParam{ 1437 StreamID: f.StreamID, 1438 EndHeaders: true, 1439 EndStream: endStream, 1440 BlockFragment: hbf, 1441 }) 1442 case splitHeader: 1443 if len(hbf) < 2 { 1444 panic("too small") 1445 } 1446 ct.fr.WriteHeaders(HeadersFrameParam{ 1447 StreamID: f.StreamID, 1448 EndHeaders: false, 1449 EndStream: endStream, 1450 BlockFragment: hbf[:1], 1451 }) 1452 ct.fr.WriteContinuation(f.StreamID, true, hbf[1:]) 1453 default: 1454 panic("bogus mode") 1455 } 1456 } 1457 // Response headers (1+ frames; 1 or 2 in this test, but never 0) 1458 { 1459 buf.Reset() 1460 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 1461 enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "declared"}) 1462 endStream = false 1463 send(oneHeader) 1464 } 1465 // Trailers: 1466 { 1467 endStream = true 1468 buf.Reset() 1469 writeTrailer(enc) 1470 send(trailers) 1471 } 1472 return nil 1473 } 1474 } 1475 } 1476 ct.run() 1477} 1478 1479// headerListSize returns the HTTP2 header list size of h. 1480// http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE 1481// http://httpwg.org/specs/rfc7540.html#MaxHeaderBlock 1482func headerListSize(h http.Header) (size uint32) { 1483 for k, vv := range h { 1484 for _, v := range vv { 1485 hf := hpack.HeaderField{Name: k, Value: v} 1486 size += hf.Size() 1487 } 1488 } 1489 return size 1490} 1491 1492// padHeaders adds data to an http.Header until headerListSize(h) == 1493// limit. Due to the way header list sizes are calculated, padHeaders 1494// cannot add fewer than len("Pad-Headers") + 32 bytes to h, and will 1495// call t.Fatal if asked to do so. PadHeaders first reserves enough 1496// space for an empty "Pad-Headers" key, then adds as many copies of 1497// filler as possible. Any remaining bytes necessary to push the 1498// header list size up to limit are added to h["Pad-Headers"]. 1499func padHeaders(t *testing.T, h http.Header, limit uint64, filler string) { 1500 if limit > 0xffffffff { 1501 t.Fatalf("padHeaders: refusing to pad to more than 2^32-1 bytes. limit = %v", limit) 1502 } 1503 hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""} 1504 minPadding := uint64(hf.Size()) 1505 size := uint64(headerListSize(h)) 1506 1507 minlimit := size + minPadding 1508 if limit < minlimit { 1509 t.Fatalf("padHeaders: limit %v < %v", limit, minlimit) 1510 } 1511 1512 // Use a fixed-width format for name so that fieldSize 1513 // remains constant. 1514 nameFmt := "Pad-Headers-%06d" 1515 hf = hpack.HeaderField{Name: fmt.Sprintf(nameFmt, 1), Value: filler} 1516 fieldSize := uint64(hf.Size()) 1517 1518 // Add as many complete filler values as possible, leaving 1519 // room for at least one empty "Pad-Headers" key. 1520 limit = limit - minPadding 1521 for i := 0; size+fieldSize < limit; i++ { 1522 name := fmt.Sprintf(nameFmt, i) 1523 h.Add(name, filler) 1524 size += fieldSize 1525 } 1526 1527 // Add enough bytes to reach limit. 1528 remain := limit - size 1529 lastValue := strings.Repeat("*", int(remain)) 1530 h.Add("Pad-Headers", lastValue) 1531} 1532 1533func TestPadHeaders(t *testing.T) { 1534 check := func(h http.Header, limit uint32, fillerLen int) { 1535 if h == nil { 1536 h = make(http.Header) 1537 } 1538 filler := strings.Repeat("f", fillerLen) 1539 padHeaders(t, h, uint64(limit), filler) 1540 gotSize := headerListSize(h) 1541 if gotSize != limit { 1542 t.Errorf("Got size = %v; want %v", gotSize, limit) 1543 } 1544 } 1545 // Try all possible combinations for small fillerLen and limit. 1546 hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""} 1547 minLimit := hf.Size() 1548 for limit := minLimit; limit <= 128; limit++ { 1549 for fillerLen := 0; uint32(fillerLen) <= limit; fillerLen++ { 1550 check(nil, limit, fillerLen) 1551 } 1552 } 1553 1554 // Try a few tests with larger limits, plus cumulative 1555 // tests. Since these tests are cumulative, tests[i+1].limit 1556 // must be >= tests[i].limit + minLimit. See the comment on 1557 // padHeaders for more info on why the limit arg has this 1558 // restriction. 1559 tests := []struct { 1560 fillerLen int 1561 limit uint32 1562 }{ 1563 { 1564 fillerLen: 64, 1565 limit: 1024, 1566 }, 1567 { 1568 fillerLen: 1024, 1569 limit: 1286, 1570 }, 1571 { 1572 fillerLen: 256, 1573 limit: 2048, 1574 }, 1575 { 1576 fillerLen: 1024, 1577 limit: 10 * 1024, 1578 }, 1579 { 1580 fillerLen: 1023, 1581 limit: 11 * 1024, 1582 }, 1583 } 1584 h := make(http.Header) 1585 for _, tc := range tests { 1586 check(nil, tc.limit, tc.fillerLen) 1587 check(h, tc.limit, tc.fillerLen) 1588 } 1589} 1590 1591func TestTransportChecksRequestHeaderListSize(t *testing.T) { 1592 st := newServerTester(t, 1593 func(w http.ResponseWriter, r *http.Request) { 1594 // Consume body & force client to send 1595 // trailers before writing response. 1596 // ioutil.ReadAll returns non-nil err for 1597 // requests that attempt to send greater than 1598 // maxHeaderListSize bytes of trailers, since 1599 // those requests generate a stream reset. 1600 ioutil.ReadAll(r.Body) 1601 r.Body.Close() 1602 }, 1603 func(ts *httptest.Server) { 1604 ts.Config.MaxHeaderBytes = 16 << 10 1605 }, 1606 optOnlyServer, 1607 optQuiet, 1608 ) 1609 defer st.Close() 1610 1611 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 1612 defer tr.CloseIdleConnections() 1613 1614 checkRoundTrip := func(req *http.Request, wantErr error, desc string) { 1615 res, err := tr.RoundTrip(req) 1616 if err != wantErr { 1617 if res != nil { 1618 res.Body.Close() 1619 } 1620 t.Errorf("%v: RoundTrip err = %v; want %v", desc, err, wantErr) 1621 return 1622 } 1623 if err == nil { 1624 if res == nil { 1625 t.Errorf("%v: response nil; want non-nil.", desc) 1626 return 1627 } 1628 defer res.Body.Close() 1629 if res.StatusCode != http.StatusOK { 1630 t.Errorf("%v: response status = %v; want %v", desc, res.StatusCode, http.StatusOK) 1631 } 1632 return 1633 } 1634 if res != nil { 1635 t.Errorf("%v: RoundTrip err = %v but response non-nil", desc, err) 1636 } 1637 } 1638 headerListSizeForRequest := func(req *http.Request) (size uint64) { 1639 contentLen := actualContentLength(req) 1640 trailers, err := commaSeparatedTrailers(req) 1641 if err != nil { 1642 t.Fatalf("headerListSizeForRequest: %v", err) 1643 } 1644 cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff} 1645 cc.henc = hpack.NewEncoder(&cc.hbuf) 1646 cc.mu.Lock() 1647 hdrs, err := cc.encodeHeaders(req, true, trailers, contentLen) 1648 cc.mu.Unlock() 1649 if err != nil { 1650 t.Fatalf("headerListSizeForRequest: %v", err) 1651 } 1652 hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(hf hpack.HeaderField) { 1653 size += uint64(hf.Size()) 1654 }) 1655 if len(hdrs) > 0 { 1656 if _, err := hpackDec.Write(hdrs); err != nil { 1657 t.Fatalf("headerListSizeForRequest: %v", err) 1658 } 1659 } 1660 return size 1661 } 1662 // Create a new Request for each test, rather than reusing the 1663 // same Request, to avoid a race when modifying req.Headers. 1664 // See https://github.com/golang/go/issues/21316 1665 newRequest := func() *http.Request { 1666 // Body must be non-nil to enable writing trailers. 1667 body := strings.NewReader("hello") 1668 req, err := http.NewRequest("POST", st.ts.URL, body) 1669 if err != nil { 1670 t.Fatalf("newRequest: NewRequest: %v", err) 1671 } 1672 return req 1673 } 1674 1675 // Make an arbitrary request to ensure we get the server's 1676 // settings frame and initialize peerMaxHeaderListSize. 1677 req := newRequest() 1678 checkRoundTrip(req, nil, "Initial request") 1679 1680 // Get the ClientConn associated with the request and validate 1681 // peerMaxHeaderListSize. 1682 addr := authorityAddr(req.URL.Scheme, req.URL.Host) 1683 cc, err := tr.connPool().GetClientConn(req, addr) 1684 if err != nil { 1685 t.Fatalf("GetClientConn: %v", err) 1686 } 1687 cc.mu.Lock() 1688 peerSize := cc.peerMaxHeaderListSize 1689 cc.mu.Unlock() 1690 st.scMu.Lock() 1691 wantSize := uint64(st.sc.maxHeaderListSize()) 1692 st.scMu.Unlock() 1693 if peerSize != wantSize { 1694 t.Errorf("peerMaxHeaderListSize = %v; want %v", peerSize, wantSize) 1695 } 1696 1697 // Sanity check peerSize. (*serverConn) maxHeaderListSize adds 1698 // 320 bytes of padding. 1699 wantHeaderBytes := uint64(st.ts.Config.MaxHeaderBytes) + 320 1700 if peerSize != wantHeaderBytes { 1701 t.Errorf("peerMaxHeaderListSize = %v; want %v.", peerSize, wantHeaderBytes) 1702 } 1703 1704 // Pad headers & trailers, but stay under peerSize. 1705 req = newRequest() 1706 req.Header = make(http.Header) 1707 req.Trailer = make(http.Header) 1708 filler := strings.Repeat("*", 1024) 1709 padHeaders(t, req.Trailer, peerSize, filler) 1710 // cc.encodeHeaders adds some default headers to the request, 1711 // so we need to leave room for those. 1712 defaultBytes := headerListSizeForRequest(req) 1713 padHeaders(t, req.Header, peerSize-defaultBytes, filler) 1714 checkRoundTrip(req, nil, "Headers & Trailers under limit") 1715 1716 // Add enough header bytes to push us over peerSize. 1717 req = newRequest() 1718 req.Header = make(http.Header) 1719 padHeaders(t, req.Header, peerSize, filler) 1720 checkRoundTrip(req, errRequestHeaderListSize, "Headers over limit") 1721 1722 // Push trailers over the limit. 1723 req = newRequest() 1724 req.Trailer = make(http.Header) 1725 padHeaders(t, req.Trailer, peerSize+1, filler) 1726 checkRoundTrip(req, errRequestHeaderListSize, "Trailers over limit") 1727 1728 // Send headers with a single large value. 1729 req = newRequest() 1730 filler = strings.Repeat("*", int(peerSize)) 1731 req.Header = make(http.Header) 1732 req.Header.Set("Big", filler) 1733 checkRoundTrip(req, errRequestHeaderListSize, "Single large header") 1734 1735 // Send trailers with a single large value. 1736 req = newRequest() 1737 req.Trailer = make(http.Header) 1738 req.Trailer.Set("Big", filler) 1739 checkRoundTrip(req, errRequestHeaderListSize, "Single large trailer") 1740} 1741 1742func TestTransportChecksResponseHeaderListSize(t *testing.T) { 1743 ct := newClientTester(t) 1744 ct.client = func() error { 1745 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 1746 res, err := ct.tr.RoundTrip(req) 1747 if err != errResponseHeaderListSize { 1748 if res != nil { 1749 res.Body.Close() 1750 } 1751 size := int64(0) 1752 for k, vv := range res.Header { 1753 for _, v := range vv { 1754 size += int64(len(k)) + int64(len(v)) + 32 1755 } 1756 } 1757 return fmt.Errorf("RoundTrip Error = %v (and %d bytes of response headers); want errResponseHeaderListSize", err, size) 1758 } 1759 return nil 1760 } 1761 ct.server = func() error { 1762 ct.greet() 1763 var buf bytes.Buffer 1764 enc := hpack.NewEncoder(&buf) 1765 1766 for { 1767 f, err := ct.fr.ReadFrame() 1768 if err != nil { 1769 return err 1770 } 1771 switch f := f.(type) { 1772 case *HeadersFrame: 1773 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 1774 large := strings.Repeat("a", 1<<10) 1775 for i := 0; i < 5042; i++ { 1776 enc.WriteField(hpack.HeaderField{Name: large, Value: large}) 1777 } 1778 if size, want := buf.Len(), 6329; size != want { 1779 // Note: this number might change if 1780 // our hpack implementation 1781 // changes. That's fine. This is 1782 // just a sanity check that our 1783 // response can fit in a single 1784 // header block fragment frame. 1785 return fmt.Errorf("encoding over 10MB of duplicate keypairs took %d bytes; expected %d", size, want) 1786 } 1787 ct.fr.WriteHeaders(HeadersFrameParam{ 1788 StreamID: f.StreamID, 1789 EndHeaders: true, 1790 EndStream: true, 1791 BlockFragment: buf.Bytes(), 1792 }) 1793 return nil 1794 } 1795 } 1796 } 1797 ct.run() 1798} 1799 1800func TestTransportCookieHeaderSplit(t *testing.T) { 1801 ct := newClientTester(t) 1802 ct.client = func() error { 1803 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 1804 req.Header.Add("Cookie", "a=b;c=d; e=f;") 1805 req.Header.Add("Cookie", "e=f;g=h; ") 1806 req.Header.Add("Cookie", "i=j") 1807 _, err := ct.tr.RoundTrip(req) 1808 return err 1809 } 1810 ct.server = func() error { 1811 ct.greet() 1812 for { 1813 f, err := ct.fr.ReadFrame() 1814 if err != nil { 1815 return err 1816 } 1817 switch f := f.(type) { 1818 case *HeadersFrame: 1819 dec := hpack.NewDecoder(initialHeaderTableSize, nil) 1820 hfs, err := dec.DecodeFull(f.HeaderBlockFragment()) 1821 if err != nil { 1822 return err 1823 } 1824 got := []string{} 1825 want := []string{"a=b", "c=d", "e=f", "e=f", "g=h", "i=j"} 1826 for _, hf := range hfs { 1827 if hf.Name == "cookie" { 1828 got = append(got, hf.Value) 1829 } 1830 } 1831 if !reflect.DeepEqual(got, want) { 1832 t.Errorf("Cookies = %#v, want %#v", got, want) 1833 } 1834 1835 var buf bytes.Buffer 1836 enc := hpack.NewEncoder(&buf) 1837 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 1838 ct.fr.WriteHeaders(HeadersFrameParam{ 1839 StreamID: f.StreamID, 1840 EndHeaders: true, 1841 EndStream: true, 1842 BlockFragment: buf.Bytes(), 1843 }) 1844 return nil 1845 } 1846 } 1847 } 1848 ct.run() 1849} 1850 1851// Test that the Transport returns a typed error from Response.Body.Read calls 1852// when the server sends an error. (here we use a panic, since that should generate 1853// a stream error, but others like cancel should be similar) 1854func TestTransportBodyReadErrorType(t *testing.T) { 1855 doPanic := make(chan bool, 1) 1856 st := newServerTester(t, 1857 func(w http.ResponseWriter, r *http.Request) { 1858 w.(http.Flusher).Flush() // force headers out 1859 <-doPanic 1860 panic("boom") 1861 }, 1862 optOnlyServer, 1863 optQuiet, 1864 ) 1865 defer st.Close() 1866 1867 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 1868 defer tr.CloseIdleConnections() 1869 c := &http.Client{Transport: tr} 1870 1871 res, err := c.Get(st.ts.URL) 1872 if err != nil { 1873 t.Fatal(err) 1874 } 1875 defer res.Body.Close() 1876 doPanic <- true 1877 buf := make([]byte, 100) 1878 n, err := res.Body.Read(buf) 1879 want := StreamError{StreamID: 0x1, Code: 0x2} 1880 if !reflect.DeepEqual(want, err) { 1881 t.Errorf("Read = %v, %#v; want error %#v", n, err, want) 1882 } 1883} 1884 1885// golang.org/issue/13924 1886// This used to fail after many iterations, especially with -race: 1887// go test -v -run=TestTransportDoubleCloseOnWriteError -count=500 -race 1888func TestTransportDoubleCloseOnWriteError(t *testing.T) { 1889 var ( 1890 mu sync.Mutex 1891 conn net.Conn // to close if set 1892 ) 1893 1894 st := newServerTester(t, 1895 func(w http.ResponseWriter, r *http.Request) { 1896 mu.Lock() 1897 defer mu.Unlock() 1898 if conn != nil { 1899 conn.Close() 1900 } 1901 }, 1902 optOnlyServer, 1903 ) 1904 defer st.Close() 1905 1906 tr := &Transport{ 1907 TLSClientConfig: tlsConfigInsecure, 1908 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { 1909 tc, err := tls.Dial(network, addr, cfg) 1910 if err != nil { 1911 return nil, err 1912 } 1913 mu.Lock() 1914 defer mu.Unlock() 1915 conn = tc 1916 return tc, nil 1917 }, 1918 } 1919 defer tr.CloseIdleConnections() 1920 c := &http.Client{Transport: tr} 1921 c.Get(st.ts.URL) 1922} 1923 1924// Test that the http1 Transport.DisableKeepAlives option is respected 1925// and connections are closed as soon as idle. 1926// See golang.org/issue/14008 1927func TestTransportDisableKeepAlives(t *testing.T) { 1928 st := newServerTester(t, 1929 func(w http.ResponseWriter, r *http.Request) { 1930 io.WriteString(w, "hi") 1931 }, 1932 optOnlyServer, 1933 ) 1934 defer st.Close() 1935 1936 connClosed := make(chan struct{}) // closed on tls.Conn.Close 1937 tr := &Transport{ 1938 t1: &http.Transport{ 1939 DisableKeepAlives: true, 1940 }, 1941 TLSClientConfig: tlsConfigInsecure, 1942 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { 1943 tc, err := tls.Dial(network, addr, cfg) 1944 if err != nil { 1945 return nil, err 1946 } 1947 return ¬eCloseConn{Conn: tc, closefn: func() { close(connClosed) }}, nil 1948 }, 1949 } 1950 c := &http.Client{Transport: tr} 1951 res, err := c.Get(st.ts.URL) 1952 if err != nil { 1953 t.Fatal(err) 1954 } 1955 if _, err := ioutil.ReadAll(res.Body); err != nil { 1956 t.Fatal(err) 1957 } 1958 defer res.Body.Close() 1959 1960 select { 1961 case <-connClosed: 1962 case <-time.After(1 * time.Second): 1963 t.Errorf("timeout") 1964 } 1965 1966} 1967 1968// Test concurrent requests with Transport.DisableKeepAlives. We can share connections, 1969// but when things are totally idle, it still needs to close. 1970func TestTransportDisableKeepAlives_Concurrency(t *testing.T) { 1971 const D = 25 * time.Millisecond 1972 st := newServerTester(t, 1973 func(w http.ResponseWriter, r *http.Request) { 1974 time.Sleep(D) 1975 io.WriteString(w, "hi") 1976 }, 1977 optOnlyServer, 1978 ) 1979 defer st.Close() 1980 1981 var dials int32 1982 var conns sync.WaitGroup 1983 tr := &Transport{ 1984 t1: &http.Transport{ 1985 DisableKeepAlives: true, 1986 }, 1987 TLSClientConfig: tlsConfigInsecure, 1988 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { 1989 tc, err := tls.Dial(network, addr, cfg) 1990 if err != nil { 1991 return nil, err 1992 } 1993 atomic.AddInt32(&dials, 1) 1994 conns.Add(1) 1995 return ¬eCloseConn{Conn: tc, closefn: func() { conns.Done() }}, nil 1996 }, 1997 } 1998 c := &http.Client{Transport: tr} 1999 var reqs sync.WaitGroup 2000 const N = 20 2001 for i := 0; i < N; i++ { 2002 reqs.Add(1) 2003 if i == N-1 { 2004 // For the final request, try to make all the 2005 // others close. This isn't verified in the 2006 // count, other than the Log statement, since 2007 // it's so timing dependent. This test is 2008 // really to make sure we don't interrupt a 2009 // valid request. 2010 time.Sleep(D * 2) 2011 } 2012 go func() { 2013 defer reqs.Done() 2014 res, err := c.Get(st.ts.URL) 2015 if err != nil { 2016 t.Error(err) 2017 return 2018 } 2019 if _, err := ioutil.ReadAll(res.Body); err != nil { 2020 t.Error(err) 2021 return 2022 } 2023 res.Body.Close() 2024 }() 2025 } 2026 reqs.Wait() 2027 conns.Wait() 2028 t.Logf("did %d dials, %d requests", atomic.LoadInt32(&dials), N) 2029} 2030 2031type noteCloseConn struct { 2032 net.Conn 2033 onceClose sync.Once 2034 closefn func() 2035} 2036 2037func (c *noteCloseConn) Close() error { 2038 c.onceClose.Do(c.closefn) 2039 return c.Conn.Close() 2040} 2041 2042func isTimeout(err error) bool { 2043 switch err := err.(type) { 2044 case nil: 2045 return false 2046 case *url.Error: 2047 return isTimeout(err.Err) 2048 case net.Error: 2049 return err.Timeout() 2050 } 2051 return false 2052} 2053 2054// Test that the http1 Transport.ResponseHeaderTimeout option and cancel is sent. 2055func TestTransportResponseHeaderTimeout_NoBody(t *testing.T) { 2056 testTransportResponseHeaderTimeout(t, false) 2057} 2058func TestTransportResponseHeaderTimeout_Body(t *testing.T) { 2059 testTransportResponseHeaderTimeout(t, true) 2060} 2061 2062func testTransportResponseHeaderTimeout(t *testing.T, body bool) { 2063 ct := newClientTester(t) 2064 ct.tr.t1 = &http.Transport{ 2065 ResponseHeaderTimeout: 5 * time.Millisecond, 2066 } 2067 ct.client = func() error { 2068 c := &http.Client{Transport: ct.tr} 2069 var err error 2070 var n int64 2071 const bodySize = 4 << 20 2072 if body { 2073 _, err = c.Post("https://dummy.tld/", "text/foo", io.LimitReader(countingReader{&n}, bodySize)) 2074 } else { 2075 _, err = c.Get("https://dummy.tld/") 2076 } 2077 if !isTimeout(err) { 2078 t.Errorf("client expected timeout error; got %#v", err) 2079 } 2080 if body && n != bodySize { 2081 t.Errorf("only read %d bytes of body; want %d", n, bodySize) 2082 } 2083 return nil 2084 } 2085 ct.server = func() error { 2086 ct.greet() 2087 for { 2088 f, err := ct.fr.ReadFrame() 2089 if err != nil { 2090 t.Logf("ReadFrame: %v", err) 2091 return nil 2092 } 2093 switch f := f.(type) { 2094 case *DataFrame: 2095 dataLen := len(f.Data()) 2096 if dataLen > 0 { 2097 if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil { 2098 return err 2099 } 2100 if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil { 2101 return err 2102 } 2103 } 2104 case *RSTStreamFrame: 2105 if f.StreamID == 1 && f.ErrCode == ErrCodeCancel { 2106 return nil 2107 } 2108 } 2109 } 2110 } 2111 ct.run() 2112} 2113 2114func TestTransportDisableCompression(t *testing.T) { 2115 const body = "sup" 2116 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 2117 want := http.Header{ 2118 "User-Agent": []string{"Go-http-client/2.0"}, 2119 } 2120 if !reflect.DeepEqual(r.Header, want) { 2121 t.Errorf("request headers = %v; want %v", r.Header, want) 2122 } 2123 }, optOnlyServer) 2124 defer st.Close() 2125 2126 tr := &Transport{ 2127 TLSClientConfig: tlsConfigInsecure, 2128 t1: &http.Transport{ 2129 DisableCompression: true, 2130 }, 2131 } 2132 defer tr.CloseIdleConnections() 2133 2134 req, err := http.NewRequest("GET", st.ts.URL, nil) 2135 if err != nil { 2136 t.Fatal(err) 2137 } 2138 res, err := tr.RoundTrip(req) 2139 if err != nil { 2140 t.Fatal(err) 2141 } 2142 defer res.Body.Close() 2143} 2144 2145// RFC 7540 section 8.1.2.2 2146func TestTransportRejectsConnHeaders(t *testing.T) { 2147 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 2148 var got []string 2149 for k := range r.Header { 2150 got = append(got, k) 2151 } 2152 sort.Strings(got) 2153 w.Header().Set("Got-Header", strings.Join(got, ",")) 2154 }, optOnlyServer) 2155 defer st.Close() 2156 2157 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 2158 defer tr.CloseIdleConnections() 2159 2160 tests := []struct { 2161 key string 2162 value []string 2163 want string 2164 }{ 2165 { 2166 key: "Upgrade", 2167 value: []string{"anything"}, 2168 want: "ERROR: http2: invalid Upgrade request header: [\"anything\"]", 2169 }, 2170 { 2171 key: "Connection", 2172 value: []string{"foo"}, 2173 want: "ERROR: http2: invalid Connection request header: [\"foo\"]", 2174 }, 2175 { 2176 key: "Connection", 2177 value: []string{"close"}, 2178 want: "Accept-Encoding,User-Agent", 2179 }, 2180 { 2181 key: "Connection", 2182 value: []string{"CLoSe"}, 2183 want: "Accept-Encoding,User-Agent", 2184 }, 2185 { 2186 key: "Connection", 2187 value: []string{"close", "something-else"}, 2188 want: "ERROR: http2: invalid Connection request header: [\"close\" \"something-else\"]", 2189 }, 2190 { 2191 key: "Connection", 2192 value: []string{"keep-alive"}, 2193 want: "Accept-Encoding,User-Agent", 2194 }, 2195 { 2196 key: "Connection", 2197 value: []string{"Keep-ALIVE"}, 2198 want: "Accept-Encoding,User-Agent", 2199 }, 2200 { 2201 key: "Proxy-Connection", // just deleted and ignored 2202 value: []string{"keep-alive"}, 2203 want: "Accept-Encoding,User-Agent", 2204 }, 2205 { 2206 key: "Transfer-Encoding", 2207 value: []string{""}, 2208 want: "Accept-Encoding,User-Agent", 2209 }, 2210 { 2211 key: "Transfer-Encoding", 2212 value: []string{"foo"}, 2213 want: "ERROR: http2: invalid Transfer-Encoding request header: [\"foo\"]", 2214 }, 2215 { 2216 key: "Transfer-Encoding", 2217 value: []string{"chunked"}, 2218 want: "Accept-Encoding,User-Agent", 2219 }, 2220 { 2221 key: "Transfer-Encoding", 2222 value: []string{"chunKed"}, // Kelvin sign 2223 want: "ERROR: http2: invalid Transfer-Encoding request header: [\"chunKed\"]", 2224 }, 2225 { 2226 key: "Transfer-Encoding", 2227 value: []string{"chunked", "other"}, 2228 want: "ERROR: http2: invalid Transfer-Encoding request header: [\"chunked\" \"other\"]", 2229 }, 2230 { 2231 key: "Content-Length", 2232 value: []string{"123"}, 2233 want: "Accept-Encoding,User-Agent", 2234 }, 2235 { 2236 key: "Keep-Alive", 2237 value: []string{"doop"}, 2238 want: "Accept-Encoding,User-Agent", 2239 }, 2240 } 2241 2242 for _, tt := range tests { 2243 req, _ := http.NewRequest("GET", st.ts.URL, nil) 2244 req.Header[tt.key] = tt.value 2245 res, err := tr.RoundTrip(req) 2246 var got string 2247 if err != nil { 2248 got = fmt.Sprintf("ERROR: %v", err) 2249 } else { 2250 got = res.Header.Get("Got-Header") 2251 res.Body.Close() 2252 } 2253 if got != tt.want { 2254 t.Errorf("For key %q, value %q, got = %q; want %q", tt.key, tt.value, got, tt.want) 2255 } 2256 } 2257} 2258 2259// Reject content-length headers containing a sign. 2260// See https://golang.org/issue/39017 2261func TestTransportRejectsContentLengthWithSign(t *testing.T) { 2262 tests := []struct { 2263 name string 2264 cl []string 2265 wantCL string 2266 }{ 2267 { 2268 name: "proper content-length", 2269 cl: []string{"3"}, 2270 wantCL: "3", 2271 }, 2272 { 2273 name: "ignore cl with plus sign", 2274 cl: []string{"+3"}, 2275 wantCL: "", 2276 }, 2277 { 2278 name: "ignore cl with minus sign", 2279 cl: []string{"-3"}, 2280 wantCL: "", 2281 }, 2282 { 2283 name: "max int64, for safe uint64->int64 conversion", 2284 cl: []string{"9223372036854775807"}, 2285 wantCL: "9223372036854775807", 2286 }, 2287 { 2288 name: "overflows int64, so ignored", 2289 cl: []string{"9223372036854775808"}, 2290 wantCL: "", 2291 }, 2292 } 2293 2294 for _, tt := range tests { 2295 tt := tt 2296 t.Run(tt.name, func(t *testing.T) { 2297 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 2298 w.Header().Set("Content-Length", tt.cl[0]) 2299 }, optOnlyServer) 2300 defer st.Close() 2301 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 2302 defer tr.CloseIdleConnections() 2303 2304 req, _ := http.NewRequest("HEAD", st.ts.URL, nil) 2305 res, err := tr.RoundTrip(req) 2306 2307 var got string 2308 if err != nil { 2309 got = fmt.Sprintf("ERROR: %v", err) 2310 } else { 2311 got = res.Header.Get("Content-Length") 2312 res.Body.Close() 2313 } 2314 2315 if got != tt.wantCL { 2316 t.Fatalf("Got: %q\nWant: %q", got, tt.wantCL) 2317 } 2318 }) 2319 } 2320} 2321 2322// golang.org/issue/14048 2323func TestTransportFailsOnInvalidHeaders(t *testing.T) { 2324 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 2325 var got []string 2326 for k := range r.Header { 2327 got = append(got, k) 2328 } 2329 sort.Strings(got) 2330 w.Header().Set("Got-Header", strings.Join(got, ",")) 2331 }, optOnlyServer) 2332 defer st.Close() 2333 2334 tests := [...]struct { 2335 h http.Header 2336 wantErr string 2337 }{ 2338 0: { 2339 h: http.Header{"with space": {"foo"}}, 2340 wantErr: `invalid HTTP header name "with space"`, 2341 }, 2342 1: { 2343 h: http.Header{"name": {"Брэд"}}, 2344 wantErr: "", // okay 2345 }, 2346 2: { 2347 h: http.Header{"имя": {"Brad"}}, 2348 wantErr: `invalid HTTP header name "имя"`, 2349 }, 2350 3: { 2351 h: http.Header{"foo": {"foo\x01bar"}}, 2352 wantErr: `invalid HTTP header value "foo\x01bar" for header "foo"`, 2353 }, 2354 } 2355 2356 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 2357 defer tr.CloseIdleConnections() 2358 2359 for i, tt := range tests { 2360 req, _ := http.NewRequest("GET", st.ts.URL, nil) 2361 req.Header = tt.h 2362 res, err := tr.RoundTrip(req) 2363 var bad bool 2364 if tt.wantErr == "" { 2365 if err != nil { 2366 bad = true 2367 t.Errorf("case %d: error = %v; want no error", i, err) 2368 } 2369 } else { 2370 if !strings.Contains(fmt.Sprint(err), tt.wantErr) { 2371 bad = true 2372 t.Errorf("case %d: error = %v; want error %q", i, err, tt.wantErr) 2373 } 2374 } 2375 if err == nil { 2376 if bad { 2377 t.Logf("case %d: server got headers %q", i, res.Header.Get("Got-Header")) 2378 } 2379 res.Body.Close() 2380 } 2381 } 2382} 2383 2384// Tests that gzipReader doesn't crash on a second Read call following 2385// the first Read call's gzip.NewReader returning an error. 2386func TestGzipReader_DoubleReadCrash(t *testing.T) { 2387 gz := &gzipReader{ 2388 body: ioutil.NopCloser(strings.NewReader("0123456789")), 2389 } 2390 var buf [1]byte 2391 n, err1 := gz.Read(buf[:]) 2392 if n != 0 || !strings.Contains(fmt.Sprint(err1), "invalid header") { 2393 t.Fatalf("Read = %v, %v; want 0, invalid header", n, err1) 2394 } 2395 n, err2 := gz.Read(buf[:]) 2396 if n != 0 || err2 != err1 { 2397 t.Fatalf("second Read = %v, %v; want 0, %v", n, err2, err1) 2398 } 2399} 2400 2401func TestTransportNewTLSConfig(t *testing.T) { 2402 tests := [...]struct { 2403 conf *tls.Config 2404 host string 2405 want *tls.Config 2406 }{ 2407 // Normal case. 2408 0: { 2409 conf: nil, 2410 host: "foo.com", 2411 want: &tls.Config{ 2412 ServerName: "foo.com", 2413 NextProtos: []string{NextProtoTLS}, 2414 }, 2415 }, 2416 2417 // User-provided name (bar.com) takes precedence: 2418 1: { 2419 conf: &tls.Config{ 2420 ServerName: "bar.com", 2421 }, 2422 host: "foo.com", 2423 want: &tls.Config{ 2424 ServerName: "bar.com", 2425 NextProtos: []string{NextProtoTLS}, 2426 }, 2427 }, 2428 2429 // NextProto is prepended: 2430 2: { 2431 conf: &tls.Config{ 2432 NextProtos: []string{"foo", "bar"}, 2433 }, 2434 host: "example.com", 2435 want: &tls.Config{ 2436 ServerName: "example.com", 2437 NextProtos: []string{NextProtoTLS, "foo", "bar"}, 2438 }, 2439 }, 2440 2441 // NextProto is not duplicated: 2442 3: { 2443 conf: &tls.Config{ 2444 NextProtos: []string{"foo", "bar", NextProtoTLS}, 2445 }, 2446 host: "example.com", 2447 want: &tls.Config{ 2448 ServerName: "example.com", 2449 NextProtos: []string{"foo", "bar", NextProtoTLS}, 2450 }, 2451 }, 2452 } 2453 for i, tt := range tests { 2454 // Ignore the session ticket keys part, which ends up populating 2455 // unexported fields in the Config: 2456 if tt.conf != nil { 2457 tt.conf.SessionTicketsDisabled = true 2458 } 2459 2460 tr := &Transport{TLSClientConfig: tt.conf} 2461 got := tr.newTLSConfig(tt.host) 2462 2463 got.SessionTicketsDisabled = false 2464 2465 if !reflect.DeepEqual(got, tt.want) { 2466 t.Errorf("%d. got %#v; want %#v", i, got, tt.want) 2467 } 2468 } 2469} 2470 2471// The Google GFE responds to HEAD requests with a HEADERS frame 2472// without END_STREAM, followed by a 0-length DATA frame with 2473// END_STREAM. Make sure we don't get confused by that. (We did.) 2474func TestTransportReadHeadResponse(t *testing.T) { 2475 ct := newClientTester(t) 2476 clientDone := make(chan struct{}) 2477 ct.client = func() error { 2478 defer close(clientDone) 2479 req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil) 2480 res, err := ct.tr.RoundTrip(req) 2481 if err != nil { 2482 return err 2483 } 2484 if res.ContentLength != 123 { 2485 return fmt.Errorf("Content-Length = %d; want 123", res.ContentLength) 2486 } 2487 slurp, err := ioutil.ReadAll(res.Body) 2488 if err != nil { 2489 return fmt.Errorf("ReadAll: %v", err) 2490 } 2491 if len(slurp) > 0 { 2492 return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp) 2493 } 2494 return nil 2495 } 2496 ct.server = func() error { 2497 ct.greet() 2498 for { 2499 f, err := ct.fr.ReadFrame() 2500 if err != nil { 2501 t.Logf("ReadFrame: %v", err) 2502 return nil 2503 } 2504 hf, ok := f.(*HeadersFrame) 2505 if !ok { 2506 continue 2507 } 2508 var buf bytes.Buffer 2509 enc := hpack.NewEncoder(&buf) 2510 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 2511 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"}) 2512 ct.fr.WriteHeaders(HeadersFrameParam{ 2513 StreamID: hf.StreamID, 2514 EndHeaders: true, 2515 EndStream: false, // as the GFE does 2516 BlockFragment: buf.Bytes(), 2517 }) 2518 ct.fr.WriteData(hf.StreamID, true, nil) 2519 2520 <-clientDone 2521 return nil 2522 } 2523 } 2524 ct.run() 2525} 2526 2527func TestTransportReadHeadResponseWithBody(t *testing.T) { 2528 // This test use not valid response format. 2529 // Discarding logger output to not spam tests output. 2530 log.SetOutput(ioutil.Discard) 2531 defer log.SetOutput(os.Stderr) 2532 2533 response := "redirecting to /elsewhere" 2534 ct := newClientTester(t) 2535 clientDone := make(chan struct{}) 2536 ct.client = func() error { 2537 defer close(clientDone) 2538 req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil) 2539 res, err := ct.tr.RoundTrip(req) 2540 if err != nil { 2541 return err 2542 } 2543 if res.ContentLength != int64(len(response)) { 2544 return fmt.Errorf("Content-Length = %d; want %d", res.ContentLength, len(response)) 2545 } 2546 slurp, err := ioutil.ReadAll(res.Body) 2547 if err != nil { 2548 return fmt.Errorf("ReadAll: %v", err) 2549 } 2550 if len(slurp) > 0 { 2551 return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp) 2552 } 2553 return nil 2554 } 2555 ct.server = func() error { 2556 ct.greet() 2557 for { 2558 f, err := ct.fr.ReadFrame() 2559 if err != nil { 2560 t.Logf("ReadFrame: %v", err) 2561 return nil 2562 } 2563 hf, ok := f.(*HeadersFrame) 2564 if !ok { 2565 continue 2566 } 2567 var buf bytes.Buffer 2568 enc := hpack.NewEncoder(&buf) 2569 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 2570 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: strconv.Itoa(len(response))}) 2571 ct.fr.WriteHeaders(HeadersFrameParam{ 2572 StreamID: hf.StreamID, 2573 EndHeaders: true, 2574 EndStream: false, 2575 BlockFragment: buf.Bytes(), 2576 }) 2577 ct.fr.WriteData(hf.StreamID, true, []byte(response)) 2578 2579 <-clientDone 2580 return nil 2581 } 2582 } 2583 ct.run() 2584} 2585 2586type neverEnding byte 2587 2588func (b neverEnding) Read(p []byte) (int, error) { 2589 for i := range p { 2590 p[i] = byte(b) 2591 } 2592 return len(p), nil 2593} 2594 2595// golang.org/issue/15425: test that a handler closing the request 2596// body doesn't terminate the stream to the peer. (It just stops 2597// readability from the handler's side, and eventually the client 2598// runs out of flow control tokens) 2599func TestTransportHandlerBodyClose(t *testing.T) { 2600 const bodySize = 10 << 20 2601 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 2602 r.Body.Close() 2603 io.Copy(w, io.LimitReader(neverEnding('A'), bodySize)) 2604 }, optOnlyServer) 2605 defer st.Close() 2606 2607 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 2608 defer tr.CloseIdleConnections() 2609 2610 g0 := runtime.NumGoroutine() 2611 2612 const numReq = 10 2613 for i := 0; i < numReq; i++ { 2614 req, err := http.NewRequest("POST", st.ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)}) 2615 if err != nil { 2616 t.Fatal(err) 2617 } 2618 res, err := tr.RoundTrip(req) 2619 if err != nil { 2620 t.Fatal(err) 2621 } 2622 n, err := io.Copy(ioutil.Discard, res.Body) 2623 res.Body.Close() 2624 if n != bodySize || err != nil { 2625 t.Fatalf("req#%d: Copy = %d, %v; want %d, nil", i, n, err, bodySize) 2626 } 2627 } 2628 tr.CloseIdleConnections() 2629 2630 if !waitCondition(5*time.Second, 100*time.Millisecond, func() bool { 2631 gd := runtime.NumGoroutine() - g0 2632 return gd < numReq/2 2633 }) { 2634 t.Errorf("appeared to leak goroutines") 2635 } 2636} 2637 2638// https://golang.org/issue/15930 2639func TestTransportFlowControl(t *testing.T) { 2640 const bufLen = 64 << 10 2641 var total int64 = 100 << 20 // 100MB 2642 if testing.Short() { 2643 total = 10 << 20 2644 } 2645 2646 var wrote int64 // updated atomically 2647 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 2648 b := make([]byte, bufLen) 2649 for wrote < total { 2650 n, err := w.Write(b) 2651 atomic.AddInt64(&wrote, int64(n)) 2652 if err != nil { 2653 t.Errorf("ResponseWriter.Write error: %v", err) 2654 break 2655 } 2656 w.(http.Flusher).Flush() 2657 } 2658 }, optOnlyServer) 2659 2660 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 2661 defer tr.CloseIdleConnections() 2662 req, err := http.NewRequest("GET", st.ts.URL, nil) 2663 if err != nil { 2664 t.Fatal("NewRequest error:", err) 2665 } 2666 resp, err := tr.RoundTrip(req) 2667 if err != nil { 2668 t.Fatal("RoundTrip error:", err) 2669 } 2670 defer resp.Body.Close() 2671 2672 var read int64 2673 b := make([]byte, bufLen) 2674 for { 2675 n, err := resp.Body.Read(b) 2676 if err == io.EOF { 2677 break 2678 } 2679 if err != nil { 2680 t.Fatal("Read error:", err) 2681 } 2682 read += int64(n) 2683 2684 const max = transportDefaultStreamFlow 2685 if w := atomic.LoadInt64(&wrote); -max > read-w || read-w > max { 2686 t.Fatalf("Too much data inflight: server wrote %v bytes but client only received %v", w, read) 2687 } 2688 2689 // Let the server get ahead of the client. 2690 time.Sleep(1 * time.Millisecond) 2691 } 2692} 2693 2694// golang.org/issue/14627 -- if the server sends a GOAWAY frame, make 2695// the Transport remember it and return it back to users (via 2696// RoundTrip or request body reads) if needed (e.g. if the server 2697// proceeds to close the TCP connection before the client gets its 2698// response) 2699func TestTransportUsesGoAwayDebugError_RoundTrip(t *testing.T) { 2700 testTransportUsesGoAwayDebugError(t, false) 2701} 2702 2703func TestTransportUsesGoAwayDebugError_Body(t *testing.T) { 2704 testTransportUsesGoAwayDebugError(t, true) 2705} 2706 2707func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) { 2708 ct := newClientTester(t) 2709 clientDone := make(chan struct{}) 2710 2711 const goAwayErrCode = ErrCodeHTTP11Required // arbitrary 2712 const goAwayDebugData = "some debug data" 2713 2714 ct.client = func() error { 2715 defer close(clientDone) 2716 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 2717 res, err := ct.tr.RoundTrip(req) 2718 if failMidBody { 2719 if err != nil { 2720 return fmt.Errorf("unexpected client RoundTrip error: %v", err) 2721 } 2722 _, err = io.Copy(ioutil.Discard, res.Body) 2723 res.Body.Close() 2724 } 2725 want := GoAwayError{ 2726 LastStreamID: 5, 2727 ErrCode: goAwayErrCode, 2728 DebugData: goAwayDebugData, 2729 } 2730 if !reflect.DeepEqual(err, want) { 2731 t.Errorf("RoundTrip error = %T: %#v, want %T (%#v)", err, err, want, want) 2732 } 2733 return nil 2734 } 2735 ct.server = func() error { 2736 ct.greet() 2737 for { 2738 f, err := ct.fr.ReadFrame() 2739 if err != nil { 2740 t.Logf("ReadFrame: %v", err) 2741 return nil 2742 } 2743 hf, ok := f.(*HeadersFrame) 2744 if !ok { 2745 continue 2746 } 2747 if failMidBody { 2748 var buf bytes.Buffer 2749 enc := hpack.NewEncoder(&buf) 2750 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 2751 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"}) 2752 ct.fr.WriteHeaders(HeadersFrameParam{ 2753 StreamID: hf.StreamID, 2754 EndHeaders: true, 2755 EndStream: false, 2756 BlockFragment: buf.Bytes(), 2757 }) 2758 } 2759 // Write two GOAWAY frames, to test that the Transport takes 2760 // the interesting parts of both. 2761 ct.fr.WriteGoAway(5, ErrCodeNo, []byte(goAwayDebugData)) 2762 ct.fr.WriteGoAway(5, goAwayErrCode, nil) 2763 ct.sc.(*net.TCPConn).CloseWrite() 2764 if runtime.GOOS == "plan9" { 2765 // CloseWrite not supported on Plan 9; Issue 17906 2766 ct.sc.(*net.TCPConn).Close() 2767 } 2768 <-clientDone 2769 return nil 2770 } 2771 } 2772 ct.run() 2773} 2774 2775func testTransportReturnsUnusedFlowControl(t *testing.T, oneDataFrame bool) { 2776 ct := newClientTester(t) 2777 2778 clientClosed := make(chan struct{}) 2779 serverWroteFirstByte := make(chan struct{}) 2780 2781 ct.client = func() error { 2782 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 2783 res, err := ct.tr.RoundTrip(req) 2784 if err != nil { 2785 return err 2786 } 2787 <-serverWroteFirstByte 2788 2789 if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 { 2790 return fmt.Errorf("body read = %v, %v; want 1, nil", n, err) 2791 } 2792 res.Body.Close() // leaving 4999 bytes unread 2793 close(clientClosed) 2794 2795 return nil 2796 } 2797 ct.server = func() error { 2798 ct.greet() 2799 2800 var hf *HeadersFrame 2801 for { 2802 f, err := ct.fr.ReadFrame() 2803 if err != nil { 2804 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) 2805 } 2806 switch f.(type) { 2807 case *WindowUpdateFrame, *SettingsFrame: 2808 continue 2809 } 2810 var ok bool 2811 hf, ok = f.(*HeadersFrame) 2812 if !ok { 2813 return fmt.Errorf("Got %T; want HeadersFrame", f) 2814 } 2815 break 2816 } 2817 2818 var buf bytes.Buffer 2819 enc := hpack.NewEncoder(&buf) 2820 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 2821 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"}) 2822 ct.fr.WriteHeaders(HeadersFrameParam{ 2823 StreamID: hf.StreamID, 2824 EndHeaders: true, 2825 EndStream: false, 2826 BlockFragment: buf.Bytes(), 2827 }) 2828 2829 // Two cases: 2830 // - Send one DATA frame with 5000 bytes. 2831 // - Send two DATA frames with 1 and 4999 bytes each. 2832 // 2833 // In both cases, the client should consume one byte of data, 2834 // refund that byte, then refund the following 4999 bytes. 2835 // 2836 // In the second case, the server waits for the client connection to 2837 // close before seconding the second DATA frame. This tests the case 2838 // where the client receives a DATA frame after it has reset the stream. 2839 if oneDataFrame { 2840 ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 5000)) 2841 close(serverWroteFirstByte) 2842 <-clientClosed 2843 } else { 2844 ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 1)) 2845 close(serverWroteFirstByte) 2846 <-clientClosed 2847 ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 4999)) 2848 } 2849 2850 waitingFor := "RSTStreamFrame" 2851 for { 2852 f, err := ct.fr.ReadFrame() 2853 if err != nil { 2854 return fmt.Errorf("ReadFrame while waiting for %s: %v", waitingFor, err) 2855 } 2856 if _, ok := f.(*SettingsFrame); ok { 2857 continue 2858 } 2859 switch waitingFor { 2860 case "RSTStreamFrame": 2861 if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel { 2862 return fmt.Errorf("Expected a RSTStreamFrame with code cancel; got %v", summarizeFrame(f)) 2863 } 2864 waitingFor = "WindowUpdateFrame" 2865 case "WindowUpdateFrame": 2866 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != 4999 { 2867 return fmt.Errorf("Expected WindowUpdateFrame for 4999 bytes; got %v", summarizeFrame(f)) 2868 } 2869 return nil 2870 } 2871 } 2872 } 2873 ct.run() 2874} 2875 2876// See golang.org/issue/16481 2877func TestTransportReturnsUnusedFlowControlSingleWrite(t *testing.T) { 2878 testTransportReturnsUnusedFlowControl(t, true) 2879} 2880 2881// See golang.org/issue/20469 2882func TestTransportReturnsUnusedFlowControlMultipleWrites(t *testing.T) { 2883 testTransportReturnsUnusedFlowControl(t, false) 2884} 2885 2886// Issue 16612: adjust flow control on open streams when transport 2887// receives SETTINGS with INITIAL_WINDOW_SIZE from server. 2888func TestTransportAdjustsFlowControl(t *testing.T) { 2889 ct := newClientTester(t) 2890 clientDone := make(chan struct{}) 2891 2892 const bodySize = 1 << 20 2893 2894 ct.client = func() error { 2895 defer ct.cc.(*net.TCPConn).CloseWrite() 2896 if runtime.GOOS == "plan9" { 2897 // CloseWrite not supported on Plan 9; Issue 17906 2898 defer ct.cc.(*net.TCPConn).Close() 2899 } 2900 defer close(clientDone) 2901 2902 req, _ := http.NewRequest("POST", "https://dummy.tld/", struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)}) 2903 res, err := ct.tr.RoundTrip(req) 2904 if err != nil { 2905 return err 2906 } 2907 res.Body.Close() 2908 return nil 2909 } 2910 ct.server = func() error { 2911 _, err := io.ReadFull(ct.sc, make([]byte, len(ClientPreface))) 2912 if err != nil { 2913 return fmt.Errorf("reading client preface: %v", err) 2914 } 2915 2916 var gotBytes int64 2917 var sentSettings bool 2918 for { 2919 f, err := ct.fr.ReadFrame() 2920 if err != nil { 2921 select { 2922 case <-clientDone: 2923 return nil 2924 default: 2925 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) 2926 } 2927 } 2928 switch f := f.(type) { 2929 case *DataFrame: 2930 gotBytes += int64(len(f.Data())) 2931 // After we've got half the client's 2932 // initial flow control window's worth 2933 // of request body data, give it just 2934 // enough flow control to finish. 2935 if gotBytes >= initialWindowSize/2 && !sentSettings { 2936 sentSettings = true 2937 2938 ct.fr.WriteSettings(Setting{ID: SettingInitialWindowSize, Val: bodySize}) 2939 ct.fr.WriteWindowUpdate(0, bodySize) 2940 ct.fr.WriteSettingsAck() 2941 } 2942 2943 if f.StreamEnded() { 2944 var buf bytes.Buffer 2945 enc := hpack.NewEncoder(&buf) 2946 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 2947 ct.fr.WriteHeaders(HeadersFrameParam{ 2948 StreamID: f.StreamID, 2949 EndHeaders: true, 2950 EndStream: true, 2951 BlockFragment: buf.Bytes(), 2952 }) 2953 } 2954 } 2955 } 2956 } 2957 ct.run() 2958} 2959 2960// See golang.org/issue/16556 2961func TestTransportReturnsDataPaddingFlowControl(t *testing.T) { 2962 ct := newClientTester(t) 2963 2964 unblockClient := make(chan bool, 1) 2965 2966 ct.client = func() error { 2967 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 2968 res, err := ct.tr.RoundTrip(req) 2969 if err != nil { 2970 return err 2971 } 2972 defer res.Body.Close() 2973 <-unblockClient 2974 return nil 2975 } 2976 ct.server = func() error { 2977 ct.greet() 2978 2979 var hf *HeadersFrame 2980 for { 2981 f, err := ct.fr.ReadFrame() 2982 if err != nil { 2983 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) 2984 } 2985 switch f.(type) { 2986 case *WindowUpdateFrame, *SettingsFrame: 2987 continue 2988 } 2989 var ok bool 2990 hf, ok = f.(*HeadersFrame) 2991 if !ok { 2992 return fmt.Errorf("Got %T; want HeadersFrame", f) 2993 } 2994 break 2995 } 2996 2997 var buf bytes.Buffer 2998 enc := hpack.NewEncoder(&buf) 2999 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 3000 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"}) 3001 ct.fr.WriteHeaders(HeadersFrameParam{ 3002 StreamID: hf.StreamID, 3003 EndHeaders: true, 3004 EndStream: false, 3005 BlockFragment: buf.Bytes(), 3006 }) 3007 pad := make([]byte, 5) 3008 ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream 3009 3010 f, err := ct.readNonSettingsFrame() 3011 if err != nil { 3012 return fmt.Errorf("ReadFrame while waiting for first WindowUpdateFrame: %v", err) 3013 } 3014 wantBack := uint32(len(pad)) + 1 // one byte for the length of the padding 3015 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID != 0 { 3016 return fmt.Errorf("Expected conn WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f)) 3017 } 3018 3019 f, err = ct.readNonSettingsFrame() 3020 if err != nil { 3021 return fmt.Errorf("ReadFrame while waiting for second WindowUpdateFrame: %v", err) 3022 } 3023 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID == 0 { 3024 return fmt.Errorf("Expected stream WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f)) 3025 } 3026 unblockClient <- true 3027 return nil 3028 } 3029 ct.run() 3030} 3031 3032// golang.org/issue/16572 -- RoundTrip shouldn't hang when it gets a 3033// StreamError as a result of the response HEADERS 3034func TestTransportReturnsErrorOnBadResponseHeaders(t *testing.T) { 3035 ct := newClientTester(t) 3036 3037 ct.client = func() error { 3038 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 3039 res, err := ct.tr.RoundTrip(req) 3040 if err == nil { 3041 res.Body.Close() 3042 return errors.New("unexpected successful GET") 3043 } 3044 want := StreamError{1, ErrCodeProtocol, headerFieldNameError(" content-type")} 3045 if !reflect.DeepEqual(want, err) { 3046 t.Errorf("RoundTrip error = %#v; want %#v", err, want) 3047 } 3048 return nil 3049 } 3050 ct.server = func() error { 3051 ct.greet() 3052 3053 hf, err := ct.firstHeaders() 3054 if err != nil { 3055 return err 3056 } 3057 3058 var buf bytes.Buffer 3059 enc := hpack.NewEncoder(&buf) 3060 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 3061 enc.WriteField(hpack.HeaderField{Name: " content-type", Value: "bogus"}) // bogus spaces 3062 ct.fr.WriteHeaders(HeadersFrameParam{ 3063 StreamID: hf.StreamID, 3064 EndHeaders: true, 3065 EndStream: false, 3066 BlockFragment: buf.Bytes(), 3067 }) 3068 3069 for { 3070 fr, err := ct.readFrame() 3071 if err != nil { 3072 return fmt.Errorf("error waiting for RST_STREAM from client: %v", err) 3073 } 3074 if _, ok := fr.(*SettingsFrame); ok { 3075 continue 3076 } 3077 if rst, ok := fr.(*RSTStreamFrame); !ok || rst.StreamID != 1 || rst.ErrCode != ErrCodeProtocol { 3078 t.Errorf("Frame = %v; want RST_STREAM for stream 1 with ErrCodeProtocol", summarizeFrame(fr)) 3079 } 3080 break 3081 } 3082 3083 return nil 3084 } 3085 ct.run() 3086} 3087 3088// byteAndEOFReader returns is in an io.Reader which reads one byte 3089// (the underlying byte) and io.EOF at once in its Read call. 3090type byteAndEOFReader byte 3091 3092func (b byteAndEOFReader) Read(p []byte) (n int, err error) { 3093 if len(p) == 0 { 3094 panic("unexpected useless call") 3095 } 3096 p[0] = byte(b) 3097 return 1, io.EOF 3098} 3099 3100// Issue 16788: the Transport had a regression where it started 3101// sending a spurious DATA frame with a duplicate END_STREAM bit after 3102// the request body writer goroutine had already read an EOF from the 3103// Request.Body and included the END_STREAM on a data-carrying DATA 3104// frame. 3105// 3106// Notably, to trigger this, the requests need to use a Request.Body 3107// which returns (non-0, io.EOF) and also needs to set the ContentLength 3108// explicitly. 3109func TestTransportBodyDoubleEndStream(t *testing.T) { 3110 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 3111 // Nothing. 3112 }, optOnlyServer) 3113 defer st.Close() 3114 3115 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 3116 defer tr.CloseIdleConnections() 3117 3118 for i := 0; i < 2; i++ { 3119 req, _ := http.NewRequest("POST", st.ts.URL, byteAndEOFReader('a')) 3120 req.ContentLength = 1 3121 res, err := tr.RoundTrip(req) 3122 if err != nil { 3123 t.Fatalf("failure on req %d: %v", i+1, err) 3124 } 3125 defer res.Body.Close() 3126 } 3127} 3128 3129// golang.org/issue/16847, golang.org/issue/19103 3130func TestTransportRequestPathPseudo(t *testing.T) { 3131 type result struct { 3132 path string 3133 err string 3134 } 3135 tests := []struct { 3136 req *http.Request 3137 want result 3138 }{ 3139 0: { 3140 req: &http.Request{ 3141 Method: "GET", 3142 URL: &url.URL{ 3143 Host: "foo.com", 3144 Path: "/foo", 3145 }, 3146 }, 3147 want: result{path: "/foo"}, 3148 }, 3149 // In Go 1.7, we accepted paths of "//foo". 3150 // In Go 1.8, we rejected it (issue 16847). 3151 // In Go 1.9, we accepted it again (issue 19103). 3152 1: { 3153 req: &http.Request{ 3154 Method: "GET", 3155 URL: &url.URL{ 3156 Host: "foo.com", 3157 Path: "//foo", 3158 }, 3159 }, 3160 want: result{path: "//foo"}, 3161 }, 3162 3163 // Opaque with //$Matching_Hostname/path 3164 2: { 3165 req: &http.Request{ 3166 Method: "GET", 3167 URL: &url.URL{ 3168 Scheme: "https", 3169 Opaque: "//foo.com/path", 3170 Host: "foo.com", 3171 Path: "/ignored", 3172 }, 3173 }, 3174 want: result{path: "/path"}, 3175 }, 3176 3177 // Opaque with some other Request.Host instead: 3178 3: { 3179 req: &http.Request{ 3180 Method: "GET", 3181 Host: "bar.com", 3182 URL: &url.URL{ 3183 Scheme: "https", 3184 Opaque: "//bar.com/path", 3185 Host: "foo.com", 3186 Path: "/ignored", 3187 }, 3188 }, 3189 want: result{path: "/path"}, 3190 }, 3191 3192 // Opaque without the leading "//": 3193 4: { 3194 req: &http.Request{ 3195 Method: "GET", 3196 URL: &url.URL{ 3197 Opaque: "/path", 3198 Host: "foo.com", 3199 Path: "/ignored", 3200 }, 3201 }, 3202 want: result{path: "/path"}, 3203 }, 3204 3205 // Opaque we can't handle: 3206 5: { 3207 req: &http.Request{ 3208 Method: "GET", 3209 URL: &url.URL{ 3210 Scheme: "https", 3211 Opaque: "//unknown_host/path", 3212 Host: "foo.com", 3213 Path: "/ignored", 3214 }, 3215 }, 3216 want: result{err: `invalid request :path "https://unknown_host/path" from URL.Opaque = "//unknown_host/path"`}, 3217 }, 3218 3219 // A CONNECT request: 3220 6: { 3221 req: &http.Request{ 3222 Method: "CONNECT", 3223 URL: &url.URL{ 3224 Host: "foo.com", 3225 }, 3226 }, 3227 want: result{}, 3228 }, 3229 } 3230 for i, tt := range tests { 3231 cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff} 3232 cc.henc = hpack.NewEncoder(&cc.hbuf) 3233 cc.mu.Lock() 3234 hdrs, err := cc.encodeHeaders(tt.req, false, "", -1) 3235 cc.mu.Unlock() 3236 var got result 3237 hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(f hpack.HeaderField) { 3238 if f.Name == ":path" { 3239 got.path = f.Value 3240 } 3241 }) 3242 if err != nil { 3243 got.err = err.Error() 3244 } else if len(hdrs) > 0 { 3245 if _, err := hpackDec.Write(hdrs); err != nil { 3246 t.Errorf("%d. bogus hpack: %v", i, err) 3247 continue 3248 } 3249 } 3250 if got != tt.want { 3251 t.Errorf("%d. got %+v; want %+v", i, got, tt.want) 3252 } 3253 3254 } 3255 3256} 3257 3258// golang.org/issue/17071 -- don't sniff the first byte of the request body 3259// before we've determined that the ClientConn is usable. 3260func TestRoundTripDoesntConsumeRequestBodyEarly(t *testing.T) { 3261 const body = "foo" 3262 req, _ := http.NewRequest("POST", "http://foo.com/", ioutil.NopCloser(strings.NewReader(body))) 3263 cc := &ClientConn{ 3264 closed: true, 3265 } 3266 _, err := cc.RoundTrip(req) 3267 if err != errClientConnUnusable { 3268 t.Fatalf("RoundTrip = %v; want errClientConnUnusable", err) 3269 } 3270 slurp, err := ioutil.ReadAll(req.Body) 3271 if err != nil { 3272 t.Errorf("ReadAll = %v", err) 3273 } 3274 if string(slurp) != body { 3275 t.Errorf("Body = %q; want %q", slurp, body) 3276 } 3277} 3278 3279func TestClientConnPing(t *testing.T) { 3280 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer) 3281 defer st.Close() 3282 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 3283 defer tr.CloseIdleConnections() 3284 ctx := context.Background() 3285 cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false) 3286 if err != nil { 3287 t.Fatal(err) 3288 } 3289 if err = cc.Ping(context.Background()); err != nil { 3290 t.Fatal(err) 3291 } 3292} 3293 3294// Issue 16974: if the server sent a DATA frame after the user 3295// canceled the Transport's Request, the Transport previously wrote to a 3296// closed pipe, got an error, and ended up closing the whole TCP 3297// connection. 3298func TestTransportCancelDataResponseRace(t *testing.T) { 3299 cancel := make(chan struct{}) 3300 clientGotError := make(chan bool, 1) 3301 3302 const msg = "Hello." 3303 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 3304 if strings.Contains(r.URL.Path, "/hello") { 3305 time.Sleep(50 * time.Millisecond) 3306 io.WriteString(w, msg) 3307 return 3308 } 3309 for i := 0; i < 50; i++ { 3310 io.WriteString(w, "Some data.") 3311 w.(http.Flusher).Flush() 3312 if i == 2 { 3313 close(cancel) 3314 <-clientGotError 3315 } 3316 time.Sleep(10 * time.Millisecond) 3317 } 3318 }, optOnlyServer) 3319 defer st.Close() 3320 3321 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 3322 defer tr.CloseIdleConnections() 3323 3324 c := &http.Client{Transport: tr} 3325 req, _ := http.NewRequest("GET", st.ts.URL, nil) 3326 req.Cancel = cancel 3327 res, err := c.Do(req) 3328 if err != nil { 3329 t.Fatal(err) 3330 } 3331 if _, err = io.Copy(ioutil.Discard, res.Body); err == nil { 3332 t.Fatal("unexpected success") 3333 } 3334 clientGotError <- true 3335 3336 res, err = c.Get(st.ts.URL + "/hello") 3337 if err != nil { 3338 t.Fatal(err) 3339 } 3340 slurp, err := ioutil.ReadAll(res.Body) 3341 if err != nil { 3342 t.Fatal(err) 3343 } 3344 if string(slurp) != msg { 3345 t.Errorf("Got = %q; want %q", slurp, msg) 3346 } 3347} 3348 3349// Issue 21316: It should be safe to reuse an http.Request after the 3350// request has completed. 3351func TestTransportNoRaceOnRequestObjectAfterRequestComplete(t *testing.T) { 3352 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 3353 w.WriteHeader(200) 3354 io.WriteString(w, "body") 3355 }, optOnlyServer) 3356 defer st.Close() 3357 3358 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 3359 defer tr.CloseIdleConnections() 3360 3361 req, _ := http.NewRequest("GET", st.ts.URL, nil) 3362 resp, err := tr.RoundTrip(req) 3363 if err != nil { 3364 t.Fatal(err) 3365 } 3366 if _, err = io.Copy(ioutil.Discard, resp.Body); err != nil { 3367 t.Fatalf("error reading response body: %v", err) 3368 } 3369 if err := resp.Body.Close(); err != nil { 3370 t.Fatalf("error closing response body: %v", err) 3371 } 3372 3373 // This access of req.Header should not race with code in the transport. 3374 req.Header = http.Header{} 3375} 3376 3377func TestTransportCloseAfterLostPing(t *testing.T) { 3378 clientDone := make(chan struct{}) 3379 ct := newClientTester(t) 3380 ct.tr.PingTimeout = 1 * time.Second 3381 ct.tr.ReadIdleTimeout = 1 * time.Second 3382 ct.client = func() error { 3383 defer ct.cc.(*net.TCPConn).CloseWrite() 3384 defer close(clientDone) 3385 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 3386 _, err := ct.tr.RoundTrip(req) 3387 if err == nil || !strings.Contains(err.Error(), "client connection lost") { 3388 return fmt.Errorf("expected to get error about \"connection lost\", got %v", err) 3389 } 3390 return nil 3391 } 3392 ct.server = func() error { 3393 ct.greet() 3394 <-clientDone 3395 return nil 3396 } 3397 ct.run() 3398} 3399 3400func TestTransportPingWhenReading(t *testing.T) { 3401 testCases := []struct { 3402 name string 3403 readIdleTimeout time.Duration 3404 deadline time.Duration 3405 expectedPingCount int 3406 }{ 3407 { 3408 name: "two pings", 3409 readIdleTimeout: 100 * time.Millisecond, 3410 deadline: time.Second, 3411 expectedPingCount: 2, 3412 }, 3413 { 3414 name: "zero ping", 3415 readIdleTimeout: time.Second, 3416 deadline: 200 * time.Millisecond, 3417 expectedPingCount: 0, 3418 }, 3419 { 3420 name: "0 readIdleTimeout means no ping", 3421 readIdleTimeout: 0 * time.Millisecond, 3422 deadline: 500 * time.Millisecond, 3423 expectedPingCount: 0, 3424 }, 3425 } 3426 3427 for _, tc := range testCases { 3428 tc := tc // capture range variable 3429 t.Run(tc.name, func(t *testing.T) { 3430 testTransportPingWhenReading(t, tc.readIdleTimeout, tc.deadline, tc.expectedPingCount) 3431 }) 3432 } 3433} 3434 3435func testTransportPingWhenReading(t *testing.T, readIdleTimeout, deadline time.Duration, expectedPingCount int) { 3436 var pingCount int 3437 ct := newClientTester(t) 3438 ct.tr.PingTimeout = 10 * time.Millisecond 3439 ct.tr.ReadIdleTimeout = readIdleTimeout 3440 3441 ctx, cancel := context.WithTimeout(context.Background(), deadline) 3442 defer cancel() 3443 ct.client = func() error { 3444 defer ct.cc.(*net.TCPConn).CloseWrite() 3445 if runtime.GOOS == "plan9" { 3446 // CloseWrite not supported on Plan 9; Issue 17906 3447 defer ct.cc.(*net.TCPConn).Close() 3448 } 3449 req, _ := http.NewRequestWithContext(ctx, "GET", "https://dummy.tld/", nil) 3450 res, err := ct.tr.RoundTrip(req) 3451 if err != nil { 3452 return fmt.Errorf("RoundTrip: %v", err) 3453 } 3454 defer res.Body.Close() 3455 if res.StatusCode != 200 { 3456 return fmt.Errorf("status code = %v; want %v", res.StatusCode, 200) 3457 } 3458 _, err = ioutil.ReadAll(res.Body) 3459 if expectedPingCount == 0 && errors.Is(ctx.Err(), context.DeadlineExceeded) { 3460 return nil 3461 } 3462 3463 cancel() 3464 return err 3465 } 3466 3467 ct.server = func() error { 3468 ct.greet() 3469 var buf bytes.Buffer 3470 enc := hpack.NewEncoder(&buf) 3471 var streamID uint32 3472 for { 3473 f, err := ct.fr.ReadFrame() 3474 if err != nil { 3475 select { 3476 case <-ctx.Done(): 3477 // If the client's done, it 3478 // will have reported any 3479 // errors on its side. 3480 return nil 3481 default: 3482 return err 3483 } 3484 } 3485 switch f := f.(type) { 3486 case *WindowUpdateFrame, *SettingsFrame: 3487 case *HeadersFrame: 3488 if !f.HeadersEnded() { 3489 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) 3490 } 3491 enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(200)}) 3492 ct.fr.WriteHeaders(HeadersFrameParam{ 3493 StreamID: f.StreamID, 3494 EndHeaders: true, 3495 EndStream: false, 3496 BlockFragment: buf.Bytes(), 3497 }) 3498 streamID = f.StreamID 3499 case *PingFrame: 3500 pingCount++ 3501 if pingCount == expectedPingCount { 3502 if err := ct.fr.WriteData(streamID, true, []byte("hello, this is last server data frame")); err != nil { 3503 return err 3504 } 3505 } 3506 if err := ct.fr.WritePing(true, f.Data); err != nil { 3507 return err 3508 } 3509 case *RSTStreamFrame: 3510 default: 3511 return fmt.Errorf("Unexpected client frame %v", f) 3512 } 3513 } 3514 } 3515 ct.run() 3516} 3517 3518func TestTransportRetryAfterGOAWAY(t *testing.T) { 3519 var dialer struct { 3520 sync.Mutex 3521 count int 3522 } 3523 ct1 := make(chan *clientTester) 3524 ct2 := make(chan *clientTester) 3525 3526 ln := newLocalListener(t) 3527 defer ln.Close() 3528 3529 tr := &Transport{ 3530 TLSClientConfig: tlsConfigInsecure, 3531 } 3532 tr.DialTLS = func(network, addr string, cfg *tls.Config) (net.Conn, error) { 3533 dialer.Lock() 3534 defer dialer.Unlock() 3535 dialer.count++ 3536 if dialer.count == 3 { 3537 return nil, errors.New("unexpected number of dials") 3538 } 3539 cc, err := net.Dial("tcp", ln.Addr().String()) 3540 if err != nil { 3541 return nil, fmt.Errorf("dial error: %v", err) 3542 } 3543 sc, err := ln.Accept() 3544 if err != nil { 3545 return nil, fmt.Errorf("accept error: %v", err) 3546 } 3547 ct := &clientTester{ 3548 t: t, 3549 tr: tr, 3550 cc: cc, 3551 sc: sc, 3552 fr: NewFramer(sc, sc), 3553 } 3554 switch dialer.count { 3555 case 1: 3556 ct1 <- ct 3557 case 2: 3558 ct2 <- ct 3559 } 3560 return cc, nil 3561 } 3562 3563 errs := make(chan error, 3) 3564 3565 // Client. 3566 go func() { 3567 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 3568 res, err := tr.RoundTrip(req) 3569 if res != nil { 3570 res.Body.Close() 3571 if got := res.Header.Get("Foo"); got != "bar" { 3572 err = fmt.Errorf("foo header = %q; want bar", got) 3573 } 3574 } 3575 if err != nil { 3576 err = fmt.Errorf("RoundTrip: %v", err) 3577 } 3578 errs <- err 3579 }() 3580 3581 connToClose := make(chan io.Closer, 2) 3582 3583 // Server for the first request. 3584 go func() { 3585 ct := <-ct1 3586 3587 connToClose <- ct.cc 3588 ct.greet() 3589 hf, err := ct.firstHeaders() 3590 if err != nil { 3591 errs <- fmt.Errorf("server1 failed reading HEADERS: %v", err) 3592 return 3593 } 3594 t.Logf("server1 got %v", hf) 3595 if err := ct.fr.WriteGoAway(0 /*max id*/, ErrCodeNo, nil); err != nil { 3596 errs <- fmt.Errorf("server1 failed writing GOAWAY: %v", err) 3597 return 3598 } 3599 errs <- nil 3600 }() 3601 3602 // Server for the second request. 3603 go func() { 3604 ct := <-ct2 3605 3606 connToClose <- ct.cc 3607 ct.greet() 3608 hf, err := ct.firstHeaders() 3609 if err != nil { 3610 errs <- fmt.Errorf("server2 failed reading HEADERS: %v", err) 3611 return 3612 } 3613 t.Logf("server2 got %v", hf) 3614 3615 var buf bytes.Buffer 3616 enc := hpack.NewEncoder(&buf) 3617 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 3618 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) 3619 err = ct.fr.WriteHeaders(HeadersFrameParam{ 3620 StreamID: hf.StreamID, 3621 EndHeaders: true, 3622 EndStream: false, 3623 BlockFragment: buf.Bytes(), 3624 }) 3625 if err != nil { 3626 errs <- fmt.Errorf("server2 failed writing response HEADERS: %v", err) 3627 } else { 3628 errs <- nil 3629 } 3630 }() 3631 3632 for k := 0; k < 3; k++ { 3633 err := <-errs 3634 if err != nil { 3635 t.Error(err) 3636 } 3637 } 3638 3639 close(connToClose) 3640 for c := range connToClose { 3641 c.Close() 3642 } 3643} 3644 3645func TestTransportRetryAfterRefusedStream(t *testing.T) { 3646 clientDone := make(chan struct{}) 3647 ct := newClientTester(t) 3648 ct.client = func() error { 3649 defer ct.cc.(*net.TCPConn).CloseWrite() 3650 if runtime.GOOS == "plan9" { 3651 // CloseWrite not supported on Plan 9; Issue 17906 3652 defer ct.cc.(*net.TCPConn).Close() 3653 } 3654 defer close(clientDone) 3655 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 3656 resp, err := ct.tr.RoundTrip(req) 3657 if err != nil { 3658 return fmt.Errorf("RoundTrip: %v", err) 3659 } 3660 resp.Body.Close() 3661 if resp.StatusCode != 204 { 3662 return fmt.Errorf("Status = %v; want 204", resp.StatusCode) 3663 } 3664 return nil 3665 } 3666 ct.server = func() error { 3667 ct.greet() 3668 var buf bytes.Buffer 3669 enc := hpack.NewEncoder(&buf) 3670 nreq := 0 3671 3672 for { 3673 f, err := ct.fr.ReadFrame() 3674 if err != nil { 3675 select { 3676 case <-clientDone: 3677 // If the client's done, it 3678 // will have reported any 3679 // errors on its side. 3680 return nil 3681 default: 3682 return err 3683 } 3684 } 3685 switch f := f.(type) { 3686 case *WindowUpdateFrame, *SettingsFrame: 3687 case *HeadersFrame: 3688 if !f.HeadersEnded() { 3689 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) 3690 } 3691 nreq++ 3692 if nreq == 1 { 3693 ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream) 3694 } else { 3695 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) 3696 ct.fr.WriteHeaders(HeadersFrameParam{ 3697 StreamID: f.StreamID, 3698 EndHeaders: true, 3699 EndStream: true, 3700 BlockFragment: buf.Bytes(), 3701 }) 3702 } 3703 default: 3704 return fmt.Errorf("Unexpected client frame %v", f) 3705 } 3706 } 3707 } 3708 ct.run() 3709} 3710 3711func TestTransportRetryHasLimit(t *testing.T) { 3712 // Skip in short mode because the total expected delay is 1s+2s+4s+8s+16s=29s. 3713 if testing.Short() { 3714 t.Skip("skipping long test in short mode") 3715 } 3716 clientDone := make(chan struct{}) 3717 ct := newClientTester(t) 3718 ct.client = func() error { 3719 defer ct.cc.(*net.TCPConn).CloseWrite() 3720 if runtime.GOOS == "plan9" { 3721 // CloseWrite not supported on Plan 9; Issue 17906 3722 defer ct.cc.(*net.TCPConn).Close() 3723 } 3724 defer close(clientDone) 3725 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 3726 resp, err := ct.tr.RoundTrip(req) 3727 if err == nil { 3728 return fmt.Errorf("RoundTrip expected error, got response: %+v", resp) 3729 } 3730 t.Logf("expected error, got: %v", err) 3731 return nil 3732 } 3733 ct.server = func() error { 3734 ct.greet() 3735 for { 3736 f, err := ct.fr.ReadFrame() 3737 if err != nil { 3738 select { 3739 case <-clientDone: 3740 // If the client's done, it 3741 // will have reported any 3742 // errors on its side. 3743 return nil 3744 default: 3745 return err 3746 } 3747 } 3748 switch f := f.(type) { 3749 case *WindowUpdateFrame, *SettingsFrame: 3750 case *HeadersFrame: 3751 if !f.HeadersEnded() { 3752 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) 3753 } 3754 ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream) 3755 default: 3756 return fmt.Errorf("Unexpected client frame %v", f) 3757 } 3758 } 3759 } 3760 ct.run() 3761} 3762 3763func TestTransportResponseDataBeforeHeaders(t *testing.T) { 3764 // This test use not valid response format. 3765 // Discarding logger output to not spam tests output. 3766 log.SetOutput(ioutil.Discard) 3767 defer log.SetOutput(os.Stderr) 3768 3769 ct := newClientTester(t) 3770 ct.client = func() error { 3771 defer ct.cc.(*net.TCPConn).CloseWrite() 3772 if runtime.GOOS == "plan9" { 3773 // CloseWrite not supported on Plan 9; Issue 17906 3774 defer ct.cc.(*net.TCPConn).Close() 3775 } 3776 req := httptest.NewRequest("GET", "https://dummy.tld/", nil) 3777 // First request is normal to ensure the check is per stream and not per connection. 3778 _, err := ct.tr.RoundTrip(req) 3779 if err != nil { 3780 return fmt.Errorf("RoundTrip expected no error, got: %v", err) 3781 } 3782 // Second request returns a DATA frame with no HEADERS. 3783 resp, err := ct.tr.RoundTrip(req) 3784 if err == nil { 3785 return fmt.Errorf("RoundTrip expected error, got response: %+v", resp) 3786 } 3787 if err, ok := err.(StreamError); !ok || err.Code != ErrCodeProtocol { 3788 return fmt.Errorf("expected stream PROTOCOL_ERROR, got: %v", err) 3789 } 3790 return nil 3791 } 3792 ct.server = func() error { 3793 ct.greet() 3794 for { 3795 f, err := ct.fr.ReadFrame() 3796 if err == io.EOF { 3797 return nil 3798 } else if err != nil { 3799 return err 3800 } 3801 switch f := f.(type) { 3802 case *WindowUpdateFrame, *SettingsFrame: 3803 case *HeadersFrame: 3804 switch f.StreamID { 3805 case 1: 3806 // Send a valid response to first request. 3807 var buf bytes.Buffer 3808 enc := hpack.NewEncoder(&buf) 3809 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 3810 ct.fr.WriteHeaders(HeadersFrameParam{ 3811 StreamID: f.StreamID, 3812 EndHeaders: true, 3813 EndStream: true, 3814 BlockFragment: buf.Bytes(), 3815 }) 3816 case 3: 3817 ct.fr.WriteData(f.StreamID, true, []byte("payload")) 3818 } 3819 default: 3820 return fmt.Errorf("Unexpected client frame %v", f) 3821 } 3822 } 3823 } 3824 ct.run() 3825} 3826 3827// tests Transport.StrictMaxConcurrentStreams 3828func TestTransportRequestsStallAtServerLimit(t *testing.T) { 3829 const maxConcurrent = 2 3830 3831 greet := make(chan struct{}) // server sends initial SETTINGS frame 3832 gotRequest := make(chan struct{}) // server received a request 3833 clientDone := make(chan struct{}) 3834 3835 // Collect errors from goroutines. 3836 var wg sync.WaitGroup 3837 errs := make(chan error, 100) 3838 defer func() { 3839 wg.Wait() 3840 close(errs) 3841 for err := range errs { 3842 t.Error(err) 3843 } 3844 }() 3845 3846 // We will send maxConcurrent+2 requests. This checker goroutine waits for the 3847 // following stages: 3848 // 1. The first maxConcurrent requests are received by the server. 3849 // 2. The client will cancel the next request 3850 // 3. The server is unblocked so it can service the first maxConcurrent requests 3851 // 4. The client will send the final request 3852 wg.Add(1) 3853 unblockClient := make(chan struct{}) 3854 clientRequestCancelled := make(chan struct{}) 3855 unblockServer := make(chan struct{}) 3856 go func() { 3857 defer wg.Done() 3858 // Stage 1. 3859 for k := 0; k < maxConcurrent; k++ { 3860 <-gotRequest 3861 } 3862 // Stage 2. 3863 close(unblockClient) 3864 <-clientRequestCancelled 3865 // Stage 3: give some time for the final RoundTrip call to be scheduled and 3866 // verify that the final request is not sent. 3867 time.Sleep(50 * time.Millisecond) 3868 select { 3869 case <-gotRequest: 3870 errs <- errors.New("last request did not stall") 3871 close(unblockServer) 3872 return 3873 default: 3874 } 3875 close(unblockServer) 3876 // Stage 4. 3877 <-gotRequest 3878 }() 3879 3880 ct := newClientTester(t) 3881 ct.tr.StrictMaxConcurrentStreams = true 3882 ct.client = func() error { 3883 var wg sync.WaitGroup 3884 defer func() { 3885 wg.Wait() 3886 close(clientDone) 3887 ct.cc.(*net.TCPConn).CloseWrite() 3888 if runtime.GOOS == "plan9" { 3889 // CloseWrite not supported on Plan 9; Issue 17906 3890 ct.cc.(*net.TCPConn).Close() 3891 } 3892 }() 3893 for k := 0; k < maxConcurrent+2; k++ { 3894 wg.Add(1) 3895 go func(k int) { 3896 defer wg.Done() 3897 // Don't send the second request until after receiving SETTINGS from the server 3898 // to avoid a race where we use the default SettingMaxConcurrentStreams, which 3899 // is much larger than maxConcurrent. We have to send the first request before 3900 // waiting because the first request triggers the dial and greet. 3901 if k > 0 { 3902 <-greet 3903 } 3904 // Block until maxConcurrent requests are sent before sending any more. 3905 if k >= maxConcurrent { 3906 <-unblockClient 3907 } 3908 req, _ := http.NewRequest("GET", fmt.Sprintf("https://dummy.tld/%d", k), nil) 3909 if k == maxConcurrent { 3910 // This request will be canceled. 3911 cancel := make(chan struct{}) 3912 req.Cancel = cancel 3913 close(cancel) 3914 _, err := ct.tr.RoundTrip(req) 3915 close(clientRequestCancelled) 3916 if err == nil { 3917 errs <- fmt.Errorf("RoundTrip(%d) should have failed due to cancel", k) 3918 return 3919 } 3920 } else { 3921 resp, err := ct.tr.RoundTrip(req) 3922 if err != nil { 3923 errs <- fmt.Errorf("RoundTrip(%d): %v", k, err) 3924 return 3925 } 3926 ioutil.ReadAll(resp.Body) 3927 resp.Body.Close() 3928 if resp.StatusCode != 204 { 3929 errs <- fmt.Errorf("Status = %v; want 204", resp.StatusCode) 3930 return 3931 } 3932 } 3933 }(k) 3934 } 3935 return nil 3936 } 3937 3938 ct.server = func() error { 3939 var wg sync.WaitGroup 3940 defer wg.Wait() 3941 3942 ct.greet(Setting{SettingMaxConcurrentStreams, maxConcurrent}) 3943 3944 // Server write loop. 3945 var buf bytes.Buffer 3946 enc := hpack.NewEncoder(&buf) 3947 writeResp := make(chan uint32, maxConcurrent+1) 3948 3949 wg.Add(1) 3950 go func() { 3951 defer wg.Done() 3952 <-unblockServer 3953 for id := range writeResp { 3954 buf.Reset() 3955 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) 3956 ct.fr.WriteHeaders(HeadersFrameParam{ 3957 StreamID: id, 3958 EndHeaders: true, 3959 EndStream: true, 3960 BlockFragment: buf.Bytes(), 3961 }) 3962 } 3963 }() 3964 3965 // Server read loop. 3966 var nreq int 3967 for { 3968 f, err := ct.fr.ReadFrame() 3969 if err != nil { 3970 select { 3971 case <-clientDone: 3972 // If the client's done, it will have reported any errors on its side. 3973 return nil 3974 default: 3975 return err 3976 } 3977 } 3978 switch f := f.(type) { 3979 case *WindowUpdateFrame: 3980 case *SettingsFrame: 3981 // Wait for the client SETTINGS ack until ending the greet. 3982 close(greet) 3983 case *HeadersFrame: 3984 if !f.HeadersEnded() { 3985 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) 3986 } 3987 gotRequest <- struct{}{} 3988 nreq++ 3989 writeResp <- f.StreamID 3990 if nreq == maxConcurrent+1 { 3991 close(writeResp) 3992 } 3993 default: 3994 return fmt.Errorf("Unexpected client frame %v", f) 3995 } 3996 } 3997 } 3998 3999 ct.run() 4000} 4001 4002func TestAuthorityAddr(t *testing.T) { 4003 tests := []struct { 4004 scheme, authority string 4005 want string 4006 }{ 4007 {"http", "foo.com", "foo.com:80"}, 4008 {"https", "foo.com", "foo.com:443"}, 4009 {"https", "foo.com:1234", "foo.com:1234"}, 4010 {"https", "1.2.3.4:1234", "1.2.3.4:1234"}, 4011 {"https", "1.2.3.4", "1.2.3.4:443"}, 4012 {"https", "[::1]:1234", "[::1]:1234"}, 4013 {"https", "[::1]", "[::1]:443"}, 4014 } 4015 for _, tt := range tests { 4016 got := authorityAddr(tt.scheme, tt.authority) 4017 if got != tt.want { 4018 t.Errorf("authorityAddr(%q, %q) = %q; want %q", tt.scheme, tt.authority, got, tt.want) 4019 } 4020 } 4021} 4022 4023// Issue 20448: stop allocating for DATA frames' payload after 4024// Response.Body.Close is called. 4025func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) { 4026 megabyteZero := make([]byte, 1<<20) 4027 4028 writeErr := make(chan error, 1) 4029 4030 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 4031 w.(http.Flusher).Flush() 4032 var sum int64 4033 for i := 0; i < 100; i++ { 4034 n, err := w.Write(megabyteZero) 4035 sum += int64(n) 4036 if err != nil { 4037 writeErr <- err 4038 return 4039 } 4040 } 4041 t.Logf("wrote all %d bytes", sum) 4042 writeErr <- nil 4043 }, optOnlyServer) 4044 defer st.Close() 4045 4046 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 4047 defer tr.CloseIdleConnections() 4048 c := &http.Client{Transport: tr} 4049 res, err := c.Get(st.ts.URL) 4050 if err != nil { 4051 t.Fatal(err) 4052 } 4053 var buf [1]byte 4054 if _, err := res.Body.Read(buf[:]); err != nil { 4055 t.Error(err) 4056 } 4057 if err := res.Body.Close(); err != nil { 4058 t.Error(err) 4059 } 4060 4061 trb, ok := res.Body.(transportResponseBody) 4062 if !ok { 4063 t.Fatalf("res.Body = %T; want transportResponseBody", res.Body) 4064 } 4065 if trb.cs.bufPipe.b != nil { 4066 t.Errorf("response body pipe is still open") 4067 } 4068 4069 gotErr := <-writeErr 4070 if gotErr == nil { 4071 t.Errorf("Handler unexpectedly managed to write its entire response without getting an error") 4072 } else if gotErr != errStreamClosed { 4073 t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr) 4074 } 4075} 4076 4077// Issue 18891: make sure Request.Body == NoBody means no DATA frame 4078// is ever sent, even if empty. 4079func TestTransportNoBodyMeansNoDATA(t *testing.T) { 4080 ct := newClientTester(t) 4081 4082 unblockClient := make(chan bool) 4083 4084 ct.client = func() error { 4085 req, _ := http.NewRequest("GET", "https://dummy.tld/", http.NoBody) 4086 ct.tr.RoundTrip(req) 4087 <-unblockClient 4088 return nil 4089 } 4090 ct.server = func() error { 4091 defer close(unblockClient) 4092 defer ct.cc.(*net.TCPConn).Close() 4093 ct.greet() 4094 4095 for { 4096 f, err := ct.fr.ReadFrame() 4097 if err != nil { 4098 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) 4099 } 4100 switch f := f.(type) { 4101 default: 4102 return fmt.Errorf("Got %T; want HeadersFrame", f) 4103 case *WindowUpdateFrame, *SettingsFrame: 4104 continue 4105 case *HeadersFrame: 4106 if !f.StreamEnded() { 4107 return fmt.Errorf("got headers frame without END_STREAM") 4108 } 4109 return nil 4110 } 4111 } 4112 } 4113 ct.run() 4114} 4115 4116func benchSimpleRoundTrip(b *testing.B, nReqHeaders, nResHeader int) { 4117 defer disableGoroutineTracking()() 4118 b.ReportAllocs() 4119 st := newServerTester(b, 4120 func(w http.ResponseWriter, r *http.Request) { 4121 for i := 0; i < nResHeader; i++ { 4122 name := fmt.Sprint("A-", i) 4123 w.Header().Set(name, "*") 4124 } 4125 }, 4126 optOnlyServer, 4127 optQuiet, 4128 ) 4129 defer st.Close() 4130 4131 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 4132 defer tr.CloseIdleConnections() 4133 4134 req, err := http.NewRequest("GET", st.ts.URL, nil) 4135 if err != nil { 4136 b.Fatal(err) 4137 } 4138 4139 for i := 0; i < nReqHeaders; i++ { 4140 name := fmt.Sprint("A-", i) 4141 req.Header.Set(name, "*") 4142 } 4143 4144 b.ResetTimer() 4145 4146 for i := 0; i < b.N; i++ { 4147 res, err := tr.RoundTrip(req) 4148 if err != nil { 4149 if res != nil { 4150 res.Body.Close() 4151 } 4152 b.Fatalf("RoundTrip err = %v; want nil", err) 4153 } 4154 res.Body.Close() 4155 if res.StatusCode != http.StatusOK { 4156 b.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK) 4157 } 4158 } 4159} 4160 4161type infiniteReader struct{} 4162 4163func (r infiniteReader) Read(b []byte) (int, error) { 4164 return len(b), nil 4165} 4166 4167// Issue 20521: it is not an error to receive a response and end stream 4168// from the server without the body being consumed. 4169func TestTransportResponseAndResetWithoutConsumingBodyRace(t *testing.T) { 4170 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 4171 w.WriteHeader(http.StatusOK) 4172 }, optOnlyServer) 4173 defer st.Close() 4174 4175 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 4176 defer tr.CloseIdleConnections() 4177 4178 // The request body needs to be big enough to trigger flow control. 4179 req, _ := http.NewRequest("PUT", st.ts.URL, infiniteReader{}) 4180 res, err := tr.RoundTrip(req) 4181 if err != nil { 4182 t.Fatal(err) 4183 } 4184 if res.StatusCode != http.StatusOK { 4185 t.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK) 4186 } 4187} 4188 4189// Verify transport doesn't crash when receiving bogus response lacking a :status header. 4190// Issue 22880. 4191func TestTransportHandlesInvalidStatuslessResponse(t *testing.T) { 4192 ct := newClientTester(t) 4193 ct.client = func() error { 4194 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) 4195 _, err := ct.tr.RoundTrip(req) 4196 const substr = "malformed response from server: missing status pseudo header" 4197 if !strings.Contains(fmt.Sprint(err), substr) { 4198 return fmt.Errorf("RoundTrip error = %v; want substring %q", err, substr) 4199 } 4200 return nil 4201 } 4202 ct.server = func() error { 4203 ct.greet() 4204 var buf bytes.Buffer 4205 enc := hpack.NewEncoder(&buf) 4206 4207 for { 4208 f, err := ct.fr.ReadFrame() 4209 if err != nil { 4210 return err 4211 } 4212 switch f := f.(type) { 4213 case *HeadersFrame: 4214 enc.WriteField(hpack.HeaderField{Name: "content-type", Value: "text/html"}) // no :status header 4215 ct.fr.WriteHeaders(HeadersFrameParam{ 4216 StreamID: f.StreamID, 4217 EndHeaders: true, 4218 EndStream: false, // we'll send some DATA to try to crash the transport 4219 BlockFragment: buf.Bytes(), 4220 }) 4221 ct.fr.WriteData(f.StreamID, true, []byte("payload")) 4222 return nil 4223 } 4224 } 4225 } 4226 ct.run() 4227} 4228 4229func BenchmarkClientRequestHeaders(b *testing.B) { 4230 b.Run(" 0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0, 0) }) 4231 b.Run(" 10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 10, 0) }) 4232 b.Run(" 100 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 100, 0) }) 4233 b.Run("1000 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 1000, 0) }) 4234} 4235 4236func BenchmarkClientResponseHeaders(b *testing.B) { 4237 b.Run(" 0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0, 0) }) 4238 b.Run(" 10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0, 10) }) 4239 b.Run(" 100 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0, 100) }) 4240 b.Run("1000 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0, 1000) }) 4241} 4242 4243func activeStreams(cc *ClientConn) int { 4244 cc.mu.Lock() 4245 defer cc.mu.Unlock() 4246 return len(cc.streams) 4247} 4248 4249type closeMode int 4250 4251const ( 4252 closeAtHeaders closeMode = iota 4253 closeAtBody 4254 shutdown 4255 shutdownCancel 4256) 4257 4258// See golang.org/issue/17292 4259func testClientConnClose(t *testing.T, closeMode closeMode) { 4260 clientDone := make(chan struct{}) 4261 defer close(clientDone) 4262 handlerDone := make(chan struct{}) 4263 closeDone := make(chan struct{}) 4264 beforeHeader := func() {} 4265 bodyWrite := func(w http.ResponseWriter) {} 4266 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 4267 defer close(handlerDone) 4268 beforeHeader() 4269 w.WriteHeader(http.StatusOK) 4270 w.(http.Flusher).Flush() 4271 bodyWrite(w) 4272 select { 4273 case <-w.(http.CloseNotifier).CloseNotify(): 4274 // client closed connection before completion 4275 if closeMode == shutdown || closeMode == shutdownCancel { 4276 t.Error("expected request to complete") 4277 } 4278 case <-clientDone: 4279 if closeMode == closeAtHeaders || closeMode == closeAtBody { 4280 t.Error("expected connection closed by client") 4281 } 4282 } 4283 }, optOnlyServer) 4284 defer st.Close() 4285 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 4286 defer tr.CloseIdleConnections() 4287 ctx := context.Background() 4288 cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false) 4289 req, err := http.NewRequest("GET", st.ts.URL, nil) 4290 if err != nil { 4291 t.Fatal(err) 4292 } 4293 if closeMode == closeAtHeaders { 4294 beforeHeader = func() { 4295 if err := cc.Close(); err != nil { 4296 t.Error(err) 4297 } 4298 close(closeDone) 4299 } 4300 } 4301 var sendBody chan struct{} 4302 if closeMode == closeAtBody { 4303 sendBody = make(chan struct{}) 4304 bodyWrite = func(w http.ResponseWriter) { 4305 <-sendBody 4306 b := make([]byte, 32) 4307 w.Write(b) 4308 w.(http.Flusher).Flush() 4309 if err := cc.Close(); err != nil { 4310 t.Errorf("unexpected ClientConn close error: %v", err) 4311 } 4312 close(closeDone) 4313 w.Write(b) 4314 w.(http.Flusher).Flush() 4315 } 4316 } 4317 res, err := cc.RoundTrip(req) 4318 if res != nil { 4319 defer res.Body.Close() 4320 } 4321 if closeMode == closeAtHeaders { 4322 got := fmt.Sprint(err) 4323 want := "http2: client connection force closed via ClientConn.Close" 4324 if got != want { 4325 t.Fatalf("RoundTrip error = %v, want %v", got, want) 4326 } 4327 } else { 4328 if err != nil { 4329 t.Fatalf("RoundTrip: %v", err) 4330 } 4331 if got, want := activeStreams(cc), 1; got != want { 4332 t.Errorf("got %d active streams, want %d", got, want) 4333 } 4334 } 4335 switch closeMode { 4336 case shutdownCancel: 4337 if err = cc.Shutdown(canceledCtx); err != context.Canceled { 4338 t.Errorf("got %v, want %v", err, context.Canceled) 4339 } 4340 if cc.closing == false { 4341 t.Error("expected closing to be true") 4342 } 4343 if cc.CanTakeNewRequest() == true { 4344 t.Error("CanTakeNewRequest to return false") 4345 } 4346 if v, want := len(cc.streams), 1; v != want { 4347 t.Errorf("expected %d active streams, got %d", want, v) 4348 } 4349 clientDone <- struct{}{} 4350 <-handlerDone 4351 case shutdown: 4352 wait := make(chan struct{}) 4353 shutdownEnterWaitStateHook = func() { 4354 close(wait) 4355 shutdownEnterWaitStateHook = func() {} 4356 } 4357 defer func() { shutdownEnterWaitStateHook = func() {} }() 4358 shutdown := make(chan struct{}, 1) 4359 go func() { 4360 if err = cc.Shutdown(context.Background()); err != nil { 4361 t.Error(err) 4362 } 4363 close(shutdown) 4364 }() 4365 // Let the shutdown to enter wait state 4366 <-wait 4367 cc.mu.Lock() 4368 if cc.closing == false { 4369 t.Error("expected closing to be true") 4370 } 4371 cc.mu.Unlock() 4372 if cc.CanTakeNewRequest() == true { 4373 t.Error("CanTakeNewRequest to return false") 4374 } 4375 if got, want := activeStreams(cc), 1; got != want { 4376 t.Errorf("got %d active streams, want %d", got, want) 4377 } 4378 // Let the active request finish 4379 clientDone <- struct{}{} 4380 // Wait for the shutdown to end 4381 select { 4382 case <-shutdown: 4383 case <-time.After(2 * time.Second): 4384 t.Fatal("expected server connection to close") 4385 } 4386 case closeAtHeaders, closeAtBody: 4387 if closeMode == closeAtBody { 4388 go close(sendBody) 4389 if _, err := io.Copy(ioutil.Discard, res.Body); err == nil { 4390 t.Error("expected a Copy error, got nil") 4391 } 4392 } 4393 <-closeDone 4394 if got, want := activeStreams(cc), 0; got != want { 4395 t.Errorf("got %d active streams, want %d", got, want) 4396 } 4397 // wait for server to get the connection close notice 4398 select { 4399 case <-handlerDone: 4400 case <-time.After(2 * time.Second): 4401 t.Fatal("expected server connection to close") 4402 } 4403 } 4404} 4405 4406// The client closes the connection just after the server got the client's HEADERS 4407// frame, but before the server sends its HEADERS response back. The expected 4408// result is an error on RoundTrip explaining the client closed the connection. 4409func TestClientConnCloseAtHeaders(t *testing.T) { 4410 testClientConnClose(t, closeAtHeaders) 4411} 4412 4413// The client closes the connection between two server's response DATA frames. 4414// The expected behavior is a response body io read error on the client. 4415func TestClientConnCloseAtBody(t *testing.T) { 4416 testClientConnClose(t, closeAtBody) 4417} 4418 4419// The client sends a GOAWAY frame before the server finished processing a request. 4420// We expect the connection not to close until the request is completed. 4421func TestClientConnShutdown(t *testing.T) { 4422 testClientConnClose(t, shutdown) 4423} 4424 4425// The client sends a GOAWAY frame before the server finishes processing a request, 4426// but cancels the passed context before the request is completed. The expected 4427// behavior is the client closing the connection after the context is canceled. 4428func TestClientConnShutdownCancel(t *testing.T) { 4429 testClientConnClose(t, shutdownCancel) 4430} 4431 4432// Issue 25009: use Request.GetBody if present, even if it seems like 4433// we might not need it. Apparently something else can still read from 4434// the original request body. Data race? In any case, rewinding 4435// unconditionally on retry is a nicer model anyway and should 4436// simplify code in the future (after the Go 1.11 freeze) 4437func TestTransportUsesGetBodyWhenPresent(t *testing.T) { 4438 calls := 0 4439 someBody := func() io.ReadCloser { 4440 return struct{ io.ReadCloser }{ioutil.NopCloser(bytes.NewReader(nil))} 4441 } 4442 req := &http.Request{ 4443 Body: someBody(), 4444 GetBody: func() (io.ReadCloser, error) { 4445 calls++ 4446 return someBody(), nil 4447 }, 4448 } 4449 4450 afterBodyWrite := false // pretend we haven't read+written the body yet 4451 req2, err := shouldRetryRequest(req, errClientConnUnusable, afterBodyWrite) 4452 if err != nil { 4453 t.Fatal(err) 4454 } 4455 if calls != 1 { 4456 t.Errorf("Calls = %d; want 1", calls) 4457 } 4458 if req2 == req { 4459 t.Error("req2 changed") 4460 } 4461 if req2 == nil { 4462 t.Fatal("req2 is nil") 4463 } 4464 if req2.Body == nil { 4465 t.Fatal("req2.Body is nil") 4466 } 4467 if req2.GetBody == nil { 4468 t.Fatal("req2.GetBody is nil") 4469 } 4470 if req2.Body == req.Body { 4471 t.Error("req2.Body unchanged") 4472 } 4473} 4474 4475// Issue 22891: verify that the "https" altproto we register with net/http 4476// is a certain type: a struct with one field with our *http2.Transport in it. 4477func TestNoDialH2RoundTripperType(t *testing.T) { 4478 t1 := new(http.Transport) 4479 t2 := new(Transport) 4480 rt := noDialH2RoundTripper{t2} 4481 if err := registerHTTPSProtocol(t1, rt); err != nil { 4482 t.Fatal(err) 4483 } 4484 rv := reflect.ValueOf(rt) 4485 if rv.Type().Kind() != reflect.Struct { 4486 t.Fatalf("kind = %v; net/http expects struct", rv.Type().Kind()) 4487 } 4488 if n := rv.Type().NumField(); n != 1 { 4489 t.Fatalf("fields = %d; net/http expects 1", n) 4490 } 4491 v := rv.Field(0) 4492 if _, ok := v.Interface().(*Transport); !ok { 4493 t.Fatalf("wrong kind %T; want *Transport", v.Interface()) 4494 } 4495} 4496 4497type errReader struct { 4498 body []byte 4499 err error 4500} 4501 4502func (r *errReader) Read(p []byte) (int, error) { 4503 if len(r.body) > 0 { 4504 n := copy(p, r.body) 4505 r.body = r.body[n:] 4506 return n, nil 4507 } 4508 return 0, r.err 4509} 4510 4511func testTransportBodyReadError(t *testing.T, body []byte) { 4512 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { 4513 // So far we've only seen this be flaky on Windows and Plan 9, 4514 // perhaps due to TCP behavior on shutdowns while 4515 // unread data is in flight. This test should be 4516 // fixed, but a skip is better than annoying people 4517 // for now. 4518 t.Skipf("skipping flaky test on %s; https://golang.org/issue/31260", runtime.GOOS) 4519 } 4520 clientDone := make(chan struct{}) 4521 ct := newClientTester(t) 4522 ct.client = func() error { 4523 defer ct.cc.(*net.TCPConn).CloseWrite() 4524 if runtime.GOOS == "plan9" { 4525 // CloseWrite not supported on Plan 9; Issue 17906 4526 defer ct.cc.(*net.TCPConn).Close() 4527 } 4528 defer close(clientDone) 4529 4530 checkNoStreams := func() error { 4531 cp, ok := ct.tr.connPool().(*clientConnPool) 4532 if !ok { 4533 return fmt.Errorf("conn pool is %T; want *clientConnPool", ct.tr.connPool()) 4534 } 4535 cp.mu.Lock() 4536 defer cp.mu.Unlock() 4537 conns, ok := cp.conns["dummy.tld:443"] 4538 if !ok { 4539 return fmt.Errorf("missing connection") 4540 } 4541 if len(conns) != 1 { 4542 return fmt.Errorf("conn pool size: %v; expect 1", len(conns)) 4543 } 4544 if activeStreams(conns[0]) != 0 { 4545 return fmt.Errorf("active streams count: %v; want 0", activeStreams(conns[0])) 4546 } 4547 return nil 4548 } 4549 bodyReadError := errors.New("body read error") 4550 body := &errReader{body, bodyReadError} 4551 req, err := http.NewRequest("PUT", "https://dummy.tld/", body) 4552 if err != nil { 4553 return err 4554 } 4555 _, err = ct.tr.RoundTrip(req) 4556 if err != bodyReadError { 4557 return fmt.Errorf("err = %v; want %v", err, bodyReadError) 4558 } 4559 if err = checkNoStreams(); err != nil { 4560 return err 4561 } 4562 return nil 4563 } 4564 ct.server = func() error { 4565 ct.greet() 4566 var receivedBody []byte 4567 var resetCount int 4568 for { 4569 f, err := ct.fr.ReadFrame() 4570 t.Logf("server: ReadFrame = %v, %v", f, err) 4571 if err != nil { 4572 select { 4573 case <-clientDone: 4574 // If the client's done, it 4575 // will have reported any 4576 // errors on its side. 4577 if bytes.Compare(receivedBody, body) != 0 { 4578 return fmt.Errorf("body: %q; expected %q", receivedBody, body) 4579 } 4580 if resetCount != 1 { 4581 return fmt.Errorf("stream reset count: %v; expected: 1", resetCount) 4582 } 4583 return nil 4584 default: 4585 return err 4586 } 4587 } 4588 switch f := f.(type) { 4589 case *WindowUpdateFrame, *SettingsFrame: 4590 case *HeadersFrame: 4591 case *DataFrame: 4592 receivedBody = append(receivedBody, f.Data()...) 4593 case *RSTStreamFrame: 4594 resetCount++ 4595 default: 4596 return fmt.Errorf("Unexpected client frame %v", f) 4597 } 4598 } 4599 } 4600 ct.run() 4601} 4602 4603func TestTransportBodyReadError_Immediately(t *testing.T) { testTransportBodyReadError(t, nil) } 4604func TestTransportBodyReadError_Some(t *testing.T) { testTransportBodyReadError(t, []byte("123")) } 4605 4606// Issue 32254: verify that the client sends END_STREAM flag eagerly with the last 4607// (or in this test-case the only one) request body data frame, and does not send 4608// extra zero-len data frames. 4609func TestTransportBodyEagerEndStream(t *testing.T) { 4610 const reqBody = "some request body" 4611 const resBody = "some response body" 4612 4613 ct := newClientTester(t) 4614 ct.client = func() error { 4615 defer ct.cc.(*net.TCPConn).CloseWrite() 4616 if runtime.GOOS == "plan9" { 4617 // CloseWrite not supported on Plan 9; Issue 17906 4618 defer ct.cc.(*net.TCPConn).Close() 4619 } 4620 body := strings.NewReader(reqBody) 4621 req, err := http.NewRequest("PUT", "https://dummy.tld/", body) 4622 if err != nil { 4623 return err 4624 } 4625 _, err = ct.tr.RoundTrip(req) 4626 if err != nil { 4627 return err 4628 } 4629 return nil 4630 } 4631 ct.server = func() error { 4632 ct.greet() 4633 4634 for { 4635 f, err := ct.fr.ReadFrame() 4636 if err != nil { 4637 return err 4638 } 4639 4640 switch f := f.(type) { 4641 case *WindowUpdateFrame, *SettingsFrame: 4642 case *HeadersFrame: 4643 case *DataFrame: 4644 if !f.StreamEnded() { 4645 ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream) 4646 return fmt.Errorf("data frame without END_STREAM %v", f) 4647 } 4648 var buf bytes.Buffer 4649 enc := hpack.NewEncoder(&buf) 4650 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 4651 ct.fr.WriteHeaders(HeadersFrameParam{ 4652 StreamID: f.Header().StreamID, 4653 EndHeaders: true, 4654 EndStream: false, 4655 BlockFragment: buf.Bytes(), 4656 }) 4657 ct.fr.WriteData(f.StreamID, true, []byte(resBody)) 4658 return nil 4659 case *RSTStreamFrame: 4660 default: 4661 return fmt.Errorf("Unexpected client frame %v", f) 4662 } 4663 } 4664 } 4665 ct.run() 4666} 4667 4668type chunkReader struct { 4669 chunks [][]byte 4670} 4671 4672func (r *chunkReader) Read(p []byte) (int, error) { 4673 if len(r.chunks) > 0 { 4674 n := copy(p, r.chunks[0]) 4675 r.chunks = r.chunks[1:] 4676 return n, nil 4677 } 4678 panic("shouldn't read this many times") 4679} 4680 4681// Issue 32254: if the request body is larger than the specified 4682// content length, the client should refuse to send the extra part 4683// and abort the stream. 4684// 4685// In _len3 case, the first Read() matches the expected content length 4686// but the second read returns more data. 4687// 4688// In _len2 case, the first Read() exceeds the expected content length. 4689func TestTransportBodyLargerThanSpecifiedContentLength_len3(t *testing.T) { 4690 body := &chunkReader{[][]byte{ 4691 []byte("123"), 4692 []byte("456"), 4693 }} 4694 testTransportBodyLargerThanSpecifiedContentLength(t, body, 3) 4695} 4696 4697func TestTransportBodyLargerThanSpecifiedContentLength_len2(t *testing.T) { 4698 body := &chunkReader{[][]byte{ 4699 []byte("123"), 4700 }} 4701 testTransportBodyLargerThanSpecifiedContentLength(t, body, 2) 4702} 4703 4704func testTransportBodyLargerThanSpecifiedContentLength(t *testing.T, body *chunkReader, contentLen int64) { 4705 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 4706 r.Body.Read(make([]byte, 6)) 4707 }, optOnlyServer) 4708 defer st.Close() 4709 4710 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 4711 defer tr.CloseIdleConnections() 4712 4713 req, _ := http.NewRequest("POST", st.ts.URL, body) 4714 req.ContentLength = contentLen 4715 _, err := tr.RoundTrip(req) 4716 if err != errReqBodyTooLong { 4717 t.Fatalf("expected %v, got %v", errReqBodyTooLong, err) 4718 } 4719} 4720 4721func TestClientConnTooIdle(t *testing.T) { 4722 tests := []struct { 4723 cc func() *ClientConn 4724 want bool 4725 }{ 4726 { 4727 func() *ClientConn { 4728 return &ClientConn{idleTimeout: 5 * time.Second, lastIdle: time.Now().Add(-10 * time.Second)} 4729 }, 4730 true, 4731 }, 4732 { 4733 func() *ClientConn { 4734 return &ClientConn{idleTimeout: 5 * time.Second, lastIdle: time.Time{}} 4735 }, 4736 false, 4737 }, 4738 { 4739 func() *ClientConn { 4740 return &ClientConn{idleTimeout: 60 * time.Second, lastIdle: time.Now().Add(-10 * time.Second)} 4741 }, 4742 false, 4743 }, 4744 { 4745 func() *ClientConn { 4746 return &ClientConn{idleTimeout: 0, lastIdle: time.Now().Add(-10 * time.Second)} 4747 }, 4748 false, 4749 }, 4750 } 4751 for i, tt := range tests { 4752 got := tt.cc().tooIdleLocked() 4753 if got != tt.want { 4754 t.Errorf("%d. got %v; want %v", i, got, tt.want) 4755 } 4756 } 4757} 4758 4759type fakeConnErr struct { 4760 net.Conn 4761 writeErr error 4762 closed bool 4763} 4764 4765func (fce *fakeConnErr) Write(b []byte) (n int, err error) { 4766 return 0, fce.writeErr 4767} 4768 4769func (fce *fakeConnErr) Close() error { 4770 fce.closed = true 4771 return nil 4772} 4773 4774// issue 39337: close the connection on a failed write 4775func TestTransportNewClientConnCloseOnWriteError(t *testing.T) { 4776 tr := &Transport{} 4777 writeErr := errors.New("write error") 4778 fakeConn := &fakeConnErr{writeErr: writeErr} 4779 _, err := tr.NewClientConn(fakeConn) 4780 if err != writeErr { 4781 t.Fatalf("expected %v, got %v", writeErr, err) 4782 } 4783 if !fakeConn.closed { 4784 t.Error("expected closed conn") 4785 } 4786} 4787 4788func TestTransportRoundtripCloseOnWriteError(t *testing.T) { 4789 req, err := http.NewRequest("GET", "https://dummy.tld/", nil) 4790 if err != nil { 4791 t.Fatal(err) 4792 } 4793 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer) 4794 defer st.Close() 4795 4796 tr := &Transport{TLSClientConfig: tlsConfigInsecure} 4797 defer tr.CloseIdleConnections() 4798 ctx := context.Background() 4799 cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false) 4800 if err != nil { 4801 t.Fatal(err) 4802 } 4803 4804 writeErr := errors.New("write error") 4805 cc.wmu.Lock() 4806 cc.werr = writeErr 4807 cc.wmu.Unlock() 4808 4809 _, err = cc.RoundTrip(req) 4810 if err != writeErr { 4811 t.Fatalf("expected %v, got %v", writeErr, err) 4812 } 4813 4814 cc.mu.Lock() 4815 closed := cc.closed 4816 cc.mu.Unlock() 4817 if !closed { 4818 t.Fatal("expected closed") 4819 } 4820} 4821 4822// Issue 31192: A failed request may be retried if the body has not been read 4823// already. If the request body has started to be sent, one must wait until it 4824// is completed. 4825func TestTransportBodyRewindRace(t *testing.T) { 4826 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 4827 w.Header().Set("Connection", "close") 4828 w.WriteHeader(http.StatusOK) 4829 return 4830 }, optOnlyServer) 4831 defer st.Close() 4832 4833 tr := &http.Transport{ 4834 TLSClientConfig: tlsConfigInsecure, 4835 MaxConnsPerHost: 1, 4836 } 4837 err := ConfigureTransport(tr) 4838 if err != nil { 4839 t.Fatal(err) 4840 } 4841 client := &http.Client{ 4842 Transport: tr, 4843 } 4844 4845 const clients = 50 4846 4847 var wg sync.WaitGroup 4848 wg.Add(clients) 4849 for i := 0; i < clients; i++ { 4850 req, err := http.NewRequest("POST", st.ts.URL, bytes.NewBufferString("abcdef")) 4851 if err != nil { 4852 t.Fatalf("unexpect new request error: %v", err) 4853 } 4854 4855 go func() { 4856 defer wg.Done() 4857 res, err := client.Do(req) 4858 if err == nil { 4859 res.Body.Close() 4860 } 4861 }() 4862 } 4863 4864 wg.Wait() 4865} 4866 4867// Issue 42498: A request with a body will never be sent if the stream is 4868// reset prior to sending any data. 4869func TestTransportServerResetStreamAtHeaders(t *testing.T) { 4870 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { 4871 w.WriteHeader(http.StatusUnauthorized) 4872 return 4873 }, optOnlyServer) 4874 defer st.Close() 4875 4876 tr := &http.Transport{ 4877 TLSClientConfig: tlsConfigInsecure, 4878 MaxConnsPerHost: 1, 4879 ExpectContinueTimeout: 10 * time.Second, 4880 } 4881 4882 err := ConfigureTransport(tr) 4883 if err != nil { 4884 t.Fatal(err) 4885 } 4886 client := &http.Client{ 4887 Transport: tr, 4888 } 4889 4890 req, err := http.NewRequest("POST", st.ts.URL, errorReader{io.EOF}) 4891 if err != nil { 4892 t.Fatalf("unexpect new request error: %v", err) 4893 } 4894 req.ContentLength = 0 // so transport is tempted to sniff it 4895 req.Header.Set("Expect", "100-continue") 4896 res, err := client.Do(req) 4897 if err != nil { 4898 t.Fatal(err) 4899 } 4900 res.Body.Close() 4901} 4902