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