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.
32 "golang.org/x/net/http2/hpack"
36 extNet = flag.Bool("extnet", false, "do external network tests")
37 transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport")
38 insecure = flag.Bool("insecure", false, "insecure TLS dials") // TODO: dead code. remove?
41 var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true}
43 type testContext struct{}
45 func (testContext) Done() <-chan struct{} { return make(chan struct{}) }
46 func (testContext) Err() error { panic("should not be called") }
47 func (testContext) Deadline() (deadline time.Time, ok bool) { return time.Time{}, false }
48 func (testContext) Value(key interface{}) interface{} { return nil }
50 func TestTransportExternal(t *testing.T) {
52 t.Skip("skipping external network test")
54 req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil)
55 rt := &Transport{TLSClientConfig: tlsConfigInsecure}
56 res, err := rt.RoundTrip(req)
63 type fakeTLSConn struct {
67 func (c *fakeTLSConn) ConnectionState() tls.ConnectionState {
68 return tls.ConnectionState{
69 Version: tls.VersionTLS12,
70 CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
74 func startH2cServer(t *testing.T) net.Listener {
76 l := newLocalListener(t)
78 conn, err := l.Accept()
83 h2Server.ServeConn(&fakeTLSConn{conn}, &ServeConnOpts{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
84 fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil)
90 func TestTransportH2c(t *testing.T) {
91 l := startH2cServer(t)
93 req, err := http.NewRequest("GET", "http://"+l.Addr().String()+"/foobar", nil)
99 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
100 return net.Dial(network, addr)
103 res, err := tr.RoundTrip(req)
107 if res.ProtoMajor != 2 {
108 t.Fatal("proto not h2c")
110 body, err := ioutil.ReadAll(res.Body)
114 if got, want := string(body), "Hello, /foobar, http: true"; got != want {
115 t.Fatalf("response got %v, want %v", got, want)
119 func TestTransport(t *testing.T) {
121 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
122 io.WriteString(w, body)
126 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
127 defer tr.CloseIdleConnections()
129 req, err := http.NewRequest("GET", st.ts.URL, nil)
133 res, err := tr.RoundTrip(req)
137 defer res.Body.Close()
139 t.Logf("Got res: %+v", res)
140 if g, w := res.StatusCode, 200; g != w {
141 t.Errorf("StatusCode = %v; want %v", g, w)
143 if g, w := res.Status, "200 OK"; g != w {
144 t.Errorf("Status = %q; want %q", g, w)
146 wantHeader := http.Header{
147 "Content-Length": []string{"3"},
148 "Content-Type": []string{"text/plain; charset=utf-8"},
149 "Date": []string{"XXX"}, // see cleanDate
152 if !reflect.DeepEqual(res.Header, wantHeader) {
153 t.Errorf("res Header = %v; want %v", res.Header, wantHeader)
155 if res.Request != req {
156 t.Errorf("Response.Request = %p; want %p", res.Request, req)
159 t.Error("Response.TLS = nil; want non-nil")
161 slurp, err := ioutil.ReadAll(res.Body)
163 t.Errorf("Body read: %v", err)
164 } else if string(slurp) != body {
165 t.Errorf("Body = %q; want %q", slurp, body)
169 func onSameConn(t *testing.T, modReq func(*http.Request)) bool {
170 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
171 io.WriteString(w, r.RemoteAddr)
172 }, optOnlyServer, func(c net.Conn, st http.ConnState) {
173 t.Logf("conn %v is now state %v", c.RemoteAddr(), st)
176 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
177 defer tr.CloseIdleConnections()
178 get := func() string {
179 req, err := http.NewRequest("GET", st.ts.URL, nil)
184 res, err := tr.RoundTrip(req)
188 defer res.Body.Close()
189 slurp, err := ioutil.ReadAll(res.Body)
191 t.Fatalf("Body read: %v", err)
193 addr := strings.TrimSpace(string(slurp))
195 t.Fatalf("didn't get an addr in response")
201 return first == second
204 func TestTransportReusesConns(t *testing.T) {
205 if !onSameConn(t, func(*http.Request) {}) {
206 t.Errorf("first and second responses were on different connections")
210 func TestTransportReusesConn_RequestClose(t *testing.T) {
211 if onSameConn(t, func(r *http.Request) { r.Close = true }) {
212 t.Errorf("first and second responses were not on different connections")
216 func TestTransportReusesConn_ConnClose(t *testing.T) {
217 if onSameConn(t, func(r *http.Request) { r.Header.Set("Connection", "close") }) {
218 t.Errorf("first and second responses were not on different connections")
222 // Tests that the Transport only keeps one pending dial open per destination address.
223 // https://golang.org/issue/13397
224 func TestTransportGroupsPendingDials(t *testing.T) {
225 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
226 io.WriteString(w, r.RemoteAddr)
230 TLSClientConfig: tlsConfigInsecure,
232 defer tr.CloseIdleConnections()
235 dials = map[string]int{}
237 var wg sync.WaitGroup
238 for i := 0; i < 10; i++ {
242 req, err := http.NewRequest("GET", st.ts.URL, nil)
247 res, err := tr.RoundTrip(req)
252 defer res.Body.Close()
253 slurp, err := ioutil.ReadAll(res.Body)
255 t.Errorf("Body read: %v", err)
257 addr := strings.TrimSpace(string(slurp))
259 t.Errorf("didn't get an addr in response")
268 t.Errorf("saw %d dials; want 1: %v", len(dials), dials)
270 tr.CloseIdleConnections()
271 if err := retry(50, 10*time.Millisecond, func() error {
272 cp, ok := tr.connPool().(*clientConnPool)
274 return fmt.Errorf("Conn pool is %T; want *clientConnPool", tr.connPool())
278 if len(cp.dialing) != 0 {
279 return fmt.Errorf("dialing map = %v; want empty", cp.dialing)
281 if len(cp.conns) != 0 {
282 return fmt.Errorf("conns = %v; want empty", cp.conns)
284 if len(cp.keys) != 0 {
285 return fmt.Errorf("keys = %v; want empty", cp.keys)
289 t.Errorf("State of pool after CloseIdleConnections: %v", err)
293 func retry(tries int, delay time.Duration, fn func() error) error {
295 for i := 0; i < tries; i++ {
305 func TestTransportAbortClosesPipes(t *testing.T) {
306 shutdown := make(chan struct{})
307 st := newServerTester(t,
308 func(w http.ResponseWriter, r *http.Request) {
309 w.(http.Flusher).Flush()
315 defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
317 done := make(chan struct{})
318 requestMade := make(chan struct{})
321 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
322 req, err := http.NewRequest("GET", st.ts.URL, nil)
326 res, err := tr.RoundTrip(req)
330 defer res.Body.Close()
332 _, err = ioutil.ReadAll(res.Body)
334 t.Error("expected error from res.Body.Read")
339 // Now force the serve loop to end, via closing the connection.
341 // deadlock? that's a bug.
344 case <-time.After(3 * time.Second):
349 // TODO: merge this with TestTransportBody to make TestTransportRequest? This
350 // could be a table-driven test with extra goodies.
351 func TestTransportPath(t *testing.T) {
352 gotc := make(chan *url.URL, 1)
353 st := newServerTester(t,
354 func(w http.ResponseWriter, r *http.Request) {
361 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
362 defer tr.CloseIdleConnections()
367 surl := st.ts.URL + path + "?" + query
368 req, err := http.NewRequest("POST", surl, nil)
372 c := &http.Client{Transport: tr}
373 res, err := c.Do(req)
377 defer res.Body.Close()
379 if got.Path != path {
380 t.Errorf("Read Path = %q; want %q", got.Path, path)
382 if got.RawQuery != query {
383 t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query)
387 func randString(n int) string {
388 rnd := rand.New(rand.NewSource(int64(n)))
391 b[i] = byte(rnd.Intn(256))
396 type panicReader struct{}
398 func (panicReader) Read([]byte) (int, error) { panic("unexpected Read") }
399 func (panicReader) Close() error { panic("unexpected Close") }
401 func TestActualContentLength(t *testing.T) {
406 // Verify we don't read from Body:
408 req: &http.Request{Body: panicReader{}},
411 // nil Body means 0, regardless of ContentLength:
413 req: &http.Request{Body: nil, ContentLength: 5},
416 // ContentLength is used if set.
418 req: &http.Request{Body: panicReader{}, ContentLength: 5},
421 // http.NoBody means 0, not -1.
423 req: &http.Request{Body: go18httpNoBody()},
427 for i, tt := range tests {
428 got := actualContentLength(tt.req)
430 t.Errorf("test[%d]: got %d; want %d", i, got, tt.want)
435 func TestTransportBody(t *testing.T) {
436 bodyTests := []struct {
440 {body: "some message"},
441 {body: "some message", noContentLen: true},
442 {body: strings.Repeat("a", 1<<20), noContentLen: true},
443 {body: strings.Repeat("a", 1<<20)},
444 {body: randString(16<<10 - 1)},
445 {body: randString(16 << 10)},
446 {body: randString(16<<10 + 1)},
447 {body: randString(512<<10 - 1)},
448 {body: randString(512 << 10)},
449 {body: randString(512<<10 + 1)},
450 {body: randString(1<<20 - 1)},
451 {body: randString(1 << 20)},
452 {body: randString(1<<20 + 2)},
455 type reqInfo struct {
460 gotc := make(chan reqInfo, 1)
461 st := newServerTester(t,
462 func(w http.ResponseWriter, r *http.Request) {
463 slurp, err := ioutil.ReadAll(r.Body)
465 gotc <- reqInfo{err: err}
467 gotc <- reqInfo{req: r, slurp: slurp}
474 for i, tt := range bodyTests {
475 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
476 defer tr.CloseIdleConnections()
478 var body io.Reader = strings.NewReader(tt.body)
480 body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods
482 req, err := http.NewRequest("POST", st.ts.URL, body)
484 t.Fatalf("#%d: %v", i, err)
486 c := &http.Client{Transport: tr}
487 res, err := c.Do(req)
489 t.Fatalf("#%d: %v", i, err)
491 defer res.Body.Close()
494 t.Errorf("#%d: read error: %v", i, ri.err)
497 if got := string(ri.slurp); got != tt.body {
498 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))
500 wantLen := int64(len(tt.body))
501 if tt.noContentLen && tt.body != "" {
504 if ri.req.ContentLength != wantLen {
505 t.Errorf("#%d. handler got ContentLength = %v; want %v", i, ri.req.ContentLength, wantLen)
510 func shortString(v string) string {
512 if len(v) <= maxLen {
515 return fmt.Sprintf("%v[...%d bytes omitted...]%v", v[:maxLen/2], len(v)-maxLen, v[len(v)-maxLen/2:])
518 func TestTransportDialTLS(t *testing.T) {
519 var mu sync.Mutex // guards following
520 var gotReq, didDial bool
522 ts := newServerTester(t,
523 func(w http.ResponseWriter, r *http.Request) {
532 DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
536 cfg.InsecureSkipVerify = true
537 c, err := tls.Dial(netw, addr, cfg)
541 return c, c.Handshake()
544 defer tr.CloseIdleConnections()
545 client := &http.Client{Transport: tr}
546 res, err := client.Get(ts.ts.URL)
553 t.Error("didn't get request")
556 t.Error("didn't use dial hook")
560 func TestConfigureTransport(t *testing.T) {
561 t1 := &http.Transport{}
562 err := ConfigureTransport(t1)
563 if err == errTransportVersion {
569 if got := fmt.Sprintf("%#v", t1); !strings.Contains(got, `"h2"`) {
570 // Laziness, to avoid buildtags.
571 t.Errorf("stringification of HTTP/1 transport didn't contain \"h2\": %v", got)
573 wantNextProtos := []string{"h2", "http/1.1"}
574 if t1.TLSClientConfig == nil {
575 t.Errorf("nil t1.TLSClientConfig")
576 } else if !reflect.DeepEqual(t1.TLSClientConfig.NextProtos, wantNextProtos) {
577 t.Errorf("TLSClientConfig.NextProtos = %q; want %q", t1.TLSClientConfig.NextProtos, wantNextProtos)
579 if err := ConfigureTransport(t1); err == nil {
580 t.Error("unexpected success on second call to ConfigureTransport")
584 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
585 io.WriteString(w, r.Proto)
589 t1.TLSClientConfig.InsecureSkipVerify = true
590 c := &http.Client{Transport: t1}
591 res, err := c.Get(st.ts.URL)
595 slurp, err := ioutil.ReadAll(res.Body)
599 if got, want := string(slurp), "HTTP/2.0"; got != want {
600 t.Errorf("body = %q; want %q", got, want)
604 type capitalizeReader struct {
608 func (cr capitalizeReader) Read(p []byte) (n int, err error) {
609 n, err = cr.r.Read(p)
610 for i, b := range p[:n] {
611 if b >= 'a' && b <= 'z' {
612 p[i] = b - ('a' - 'A')
618 type flushWriter struct {
622 func (fw flushWriter) Write(p []byte) (n int, err error) {
623 n, err = fw.w.Write(p)
624 if f, ok := fw.w.(http.Flusher); ok {
630 type clientTester struct {
633 sc, cc net.Conn // server and client conn
634 fr *Framer // server's framer
639 func newClientTester(t *testing.T) *clientTester {
640 var dialOnce struct {
648 TLSClientConfig: tlsConfigInsecure,
649 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
651 defer dialOnce.Unlock()
653 return nil, errors.New("only one dial allowed in test mode")
655 dialOnce.dialed = true
660 ln := newLocalListener(t)
661 cc, err := net.Dial("tcp", ln.Addr().String())
666 sc, err := ln.Accept()
673 ct.fr = NewFramer(sc, sc)
677 func newLocalListener(t *testing.T) net.Listener {
678 ln, err := net.Listen("tcp4", "127.0.0.1:0")
682 ln, err = net.Listen("tcp6", "[::1]:0")
689 func (ct *clientTester) greet(settings ...Setting) {
690 buf := make([]byte, len(ClientPreface))
691 _, err := io.ReadFull(ct.sc, buf)
693 ct.t.Fatalf("reading client preface: %v", err)
695 f, err := ct.fr.ReadFrame()
697 ct.t.Fatalf("Reading client settings frame: %v", err)
699 if sf, ok := f.(*SettingsFrame); !ok {
700 ct.t.Fatalf("Wanted client settings frame; got %v", f)
701 _ = sf // stash it away?
703 if err := ct.fr.WriteSettings(settings...); err != nil {
706 if err := ct.fr.WriteSettingsAck(); err != nil {
711 func (ct *clientTester) readNonSettingsFrame() (Frame, error) {
713 f, err := ct.fr.ReadFrame()
717 if _, ok := f.(*SettingsFrame); ok {
724 func (ct *clientTester) cleanup() {
725 ct.tr.CloseIdleConnections()
728 func (ct *clientTester) run() {
729 errc := make(chan error, 2)
730 ct.start("client", errc, ct.client)
731 ct.start("server", errc, ct.server)
733 for i := 0; i < 2; i++ {
734 if err := <-errc; err != nil {
741 func (ct *clientTester) start(which string, errc chan<- error, fn func() error) {
747 err = fmt.Errorf("%s goroutine didn't finish.", which)
748 } else if err != nil {
749 err = fmt.Errorf("%s: %v", which, err)
758 func (ct *clientTester) readFrame() (Frame, error) {
759 return readFrameTimeout(ct.fr, 2*time.Second)
762 func (ct *clientTester) firstHeaders() (*HeadersFrame, error) {
764 f, err := ct.readFrame()
766 return nil, fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
769 case *WindowUpdateFrame, *SettingsFrame:
772 hf, ok := f.(*HeadersFrame)
774 return nil, fmt.Errorf("Got %T; want HeadersFrame", f)
780 type countingReader struct {
784 func (r countingReader) Read(p []byte) (n int, err error) {
788 atomic.AddInt64(r.n, int64(len(p)))
792 func TestTransportReqBodyAfterResponse_200(t *testing.T) { testTransportReqBodyAfterResponse(t, 200) }
793 func TestTransportReqBodyAfterResponse_403(t *testing.T) { testTransportReqBodyAfterResponse(t, 403) }
795 func testTransportReqBodyAfterResponse(t *testing.T, status int) {
796 const bodySize = 10 << 20
797 clientDone := make(chan struct{})
798 ct := newClientTester(t)
799 ct.client = func() error {
800 defer ct.cc.(*net.TCPConn).CloseWrite()
801 defer close(clientDone)
803 var n int64 // atomic
804 req, err := http.NewRequest("PUT", "https://dummy.tld/", io.LimitReader(countingReader{&n}, bodySize))
808 res, err := ct.tr.RoundTrip(req)
810 return fmt.Errorf("RoundTrip: %v", err)
812 defer res.Body.Close()
813 if res.StatusCode != status {
814 return fmt.Errorf("status code = %v; want %v", res.StatusCode, status)
816 slurp, err := ioutil.ReadAll(res.Body)
818 return fmt.Errorf("Slurp: %v", err)
821 return fmt.Errorf("unexpected body: %q", slurp)
824 if got := atomic.LoadInt64(&n); got != bodySize {
825 return fmt.Errorf("For 200 response, Transport wrote %d bytes; want %d", got, bodySize)
828 if got := atomic.LoadInt64(&n); got == 0 || got >= bodySize {
829 return fmt.Errorf("For %d response, Transport wrote %d bytes; want (0,%d) exclusive", status, got, bodySize)
834 ct.server = func() error {
837 enc := hpack.NewEncoder(&buf)
841 f, err := ct.fr.ReadFrame()
845 // If the client's done, it
846 // will have reported any
847 // errors on its side.
853 //println(fmt.Sprintf("server got frame: %v", f))
854 switch f := f.(type) {
855 case *WindowUpdateFrame, *SettingsFrame:
857 if !f.HeadersEnded() {
858 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
861 return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f)
864 dataLen := len(f.Data())
867 enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)})
868 ct.fr.WriteHeaders(HeadersFrameParam{
869 StreamID: f.StreamID,
872 BlockFragment: buf.Bytes(),
875 if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
878 if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
882 dataRecv += int64(dataLen)
884 if !closed && ((status != 200 && dataRecv > 0) ||
885 (status == 200 && dataRecv == bodySize)) {
887 if err := ct.fr.WriteData(f.StreamID, true, nil); err != nil {
892 return fmt.Errorf("Unexpected client frame %v", f)
899 // See golang.org/issue/13444
900 func TestTransportFullDuplex(t *testing.T) {
901 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
902 w.WriteHeader(200) // redundant but for clarity
903 w.(http.Flusher).Flush()
904 io.Copy(flushWriter{w}, capitalizeReader{r.Body})
905 fmt.Fprintf(w, "bye.\n")
909 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
910 defer tr.CloseIdleConnections()
911 c := &http.Client{Transport: tr}
914 req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr))
918 req.ContentLength = -1
919 res, err := c.Do(req)
923 defer res.Body.Close()
924 if res.StatusCode != 200 {
925 t.Fatalf("StatusCode = %v; want %v", res.StatusCode, 200)
927 bs := bufio.NewScanner(res.Body)
928 want := func(v string) {
930 t.Fatalf("wanted to read %q but Scan() = false, err = %v", v, bs.Err())
933 write := func(v string) {
934 _, err := io.WriteString(pw, v)
936 t.Fatalf("pipe write: %v", err)
945 if err := bs.Err(); err != nil {
950 func TestTransportConnectRequest(t *testing.T) {
951 gotc := make(chan *http.Request, 1)
952 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
957 u, err := url.Parse(st.ts.URL)
962 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
963 defer tr.CloseIdleConnections()
964 c := &http.Client{Transport: tr}
973 Header: http.Header{},
981 Header: http.Header{},
983 Host: "example.com:123",
985 want: "example.com:123",
989 for i, tt := range tests {
990 res, err := c.Do(tt.req)
992 t.Errorf("%d. RoundTrip = %v", i, err)
997 if req.Method != "CONNECT" {
998 t.Errorf("method = %q; want CONNECT", req.Method)
1000 if req.Host != tt.want {
1001 t.Errorf("Host = %q; want %q", req.Host, tt.want)
1003 if req.URL.Host != tt.want {
1004 t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want)
1012 noHeader headerType = iota // omitted
1014 splitHeader // broken into continuation on purpose
1025 // Test all 36 combinations of response frame orders:
1026 // (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) }
1027 // Generated by http://play.golang.org/p/SScqYKJYXd
1028 func TestTransportResPattern_c0h1d0t0(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f0) }
1029 func TestTransportResPattern_c0h1d0t1(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f1) }
1030 func TestTransportResPattern_c0h1d0t2(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f2) }
1031 func TestTransportResPattern_c0h1d1t0(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f0) }
1032 func TestTransportResPattern_c0h1d1t1(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f1) }
1033 func TestTransportResPattern_c0h1d1t2(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f2) }
1034 func TestTransportResPattern_c0h2d0t0(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f0) }
1035 func TestTransportResPattern_c0h2d0t1(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f1) }
1036 func TestTransportResPattern_c0h2d0t2(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f2) }
1037 func TestTransportResPattern_c0h2d1t0(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f0) }
1038 func TestTransportResPattern_c0h2d1t1(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f1) }
1039 func TestTransportResPattern_c0h2d1t2(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f2) }
1040 func TestTransportResPattern_c1h1d0t0(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f0) }
1041 func TestTransportResPattern_c1h1d0t1(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f1) }
1042 func TestTransportResPattern_c1h1d0t2(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f2) }
1043 func TestTransportResPattern_c1h1d1t0(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f0) }
1044 func TestTransportResPattern_c1h1d1t1(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f1) }
1045 func TestTransportResPattern_c1h1d1t2(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f2) }
1046 func TestTransportResPattern_c1h2d0t0(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f0) }
1047 func TestTransportResPattern_c1h2d0t1(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f1) }
1048 func TestTransportResPattern_c1h2d0t2(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f2) }
1049 func TestTransportResPattern_c1h2d1t0(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f0) }
1050 func TestTransportResPattern_c1h2d1t1(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f1) }
1051 func TestTransportResPattern_c1h2d1t2(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f2) }
1052 func TestTransportResPattern_c2h1d0t0(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f0) }
1053 func TestTransportResPattern_c2h1d0t1(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f1) }
1054 func TestTransportResPattern_c2h1d0t2(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f2) }
1055 func TestTransportResPattern_c2h1d1t0(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f0) }
1056 func TestTransportResPattern_c2h1d1t1(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f1) }
1057 func TestTransportResPattern_c2h1d1t2(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f2) }
1058 func TestTransportResPattern_c2h2d0t0(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f0) }
1059 func TestTransportResPattern_c2h2d0t1(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f1) }
1060 func TestTransportResPattern_c2h2d0t2(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f2) }
1061 func TestTransportResPattern_c2h2d1t0(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f0) }
1062 func TestTransportResPattern_c2h2d1t1(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f1) }
1063 func TestTransportResPattern_c2h2d1t2(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f2) }
1065 func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerType, withData bool, trailers headerType) {
1066 const reqBody = "some request body"
1067 const resBody = "some response body"
1069 if resHeader == noHeader {
1070 // TODO: test 100-continue followed by immediate
1071 // server stream reset, without headers in the middle?
1072 panic("invalid combination")
1075 ct := newClientTester(t)
1076 ct.client = func() error {
1077 req, _ := http.NewRequest("POST", "https://dummy.tld/", strings.NewReader(reqBody))
1078 if expect100Continue != noHeader {
1079 req.Header.Set("Expect", "100-continue")
1081 res, err := ct.tr.RoundTrip(req)
1083 return fmt.Errorf("RoundTrip: %v", err)
1085 defer res.Body.Close()
1086 if res.StatusCode != 200 {
1087 return fmt.Errorf("status code = %v; want 200", res.StatusCode)
1089 slurp, err := ioutil.ReadAll(res.Body)
1091 return fmt.Errorf("Slurp: %v", err)
1097 if string(slurp) != wantBody {
1098 return fmt.Errorf("body = %q; want %q", slurp, wantBody)
1100 if trailers == noHeader {
1101 if len(res.Trailer) > 0 {
1102 t.Errorf("Trailer = %v; want none", res.Trailer)
1105 want := http.Header{"Some-Trailer": {"some-value"}}
1106 if !reflect.DeepEqual(res.Trailer, want) {
1107 t.Errorf("Trailer = %v; want %v", res.Trailer, want)
1112 ct.server = func() error {
1114 var buf bytes.Buffer
1115 enc := hpack.NewEncoder(&buf)
1118 f, err := ct.fr.ReadFrame()
1123 send := func(mode headerType) {
1127 ct.fr.WriteHeaders(HeadersFrameParam{
1128 StreamID: f.Header().StreamID,
1130 EndStream: endStream,
1137 ct.fr.WriteHeaders(HeadersFrameParam{
1138 StreamID: f.Header().StreamID,
1140 EndStream: endStream,
1141 BlockFragment: hbf[:1],
1143 ct.fr.WriteContinuation(f.Header().StreamID, true, hbf[1:])
1148 switch f := f.(type) {
1149 case *WindowUpdateFrame, *SettingsFrame:
1151 if !f.StreamEnded() {
1152 // No need to send flow control tokens. The test request body is tiny.
1155 // Response headers (1+ frames; 1 or 2 in this test, but never 0)
1158 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1159 enc.WriteField(hpack.HeaderField{Name: "x-foo", Value: "blah"})
1160 enc.WriteField(hpack.HeaderField{Name: "x-bar", Value: "more"})
1161 if trailers != noHeader {
1162 enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "some-trailer"})
1164 endStream = withData == false && trailers == noHeader
1168 endStream = trailers == noHeader
1169 ct.fr.WriteData(f.StreamID, endStream, []byte(resBody))
1171 if trailers != noHeader {
1174 enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "some-value"})
1181 if expect100Continue != noHeader {
1183 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"})
1184 send(expect100Continue)
1192 func TestTransportReceiveUndeclaredTrailer(t *testing.T) {
1193 ct := newClientTester(t)
1194 ct.client = func() error {
1195 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
1196 res, err := ct.tr.RoundTrip(req)
1198 return fmt.Errorf("RoundTrip: %v", err)
1200 defer res.Body.Close()
1201 if res.StatusCode != 200 {
1202 return fmt.Errorf("status code = %v; want 200", res.StatusCode)
1204 slurp, err := ioutil.ReadAll(res.Body)
1206 return fmt.Errorf("res.Body ReadAll error = %q, %v; want %v", slurp, err, nil)
1209 return fmt.Errorf("body = %q; want nothing", slurp)
1211 if _, ok := res.Trailer["Some-Trailer"]; !ok {
1212 return fmt.Errorf("expected Some-Trailer")
1216 ct.server = func() error {
1220 var hf *HeadersFrame
1221 for hf == nil && n < 10 {
1222 f, err := ct.fr.ReadFrame()
1226 hf, _ = f.(*HeadersFrame)
1230 var buf bytes.Buffer
1231 enc := hpack.NewEncoder(&buf)
1233 // send headers without Trailer header
1234 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1235 ct.fr.WriteHeaders(HeadersFrameParam{
1236 StreamID: hf.StreamID,
1239 BlockFragment: buf.Bytes(),
1244 enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "I'm an undeclared Trailer!"})
1245 ct.fr.WriteHeaders(HeadersFrameParam{
1246 StreamID: hf.StreamID,
1249 BlockFragment: buf.Bytes(),
1256 func TestTransportInvalidTrailer_Pseudo1(t *testing.T) {
1257 testTransportInvalidTrailer_Pseudo(t, oneHeader)
1259 func TestTransportInvalidTrailer_Pseudo2(t *testing.T) {
1260 testTransportInvalidTrailer_Pseudo(t, splitHeader)
1262 func testTransportInvalidTrailer_Pseudo(t *testing.T, trailers headerType) {
1263 testInvalidTrailer(t, trailers, pseudoHeaderError(":colon"), func(enc *hpack.Encoder) {
1264 enc.WriteField(hpack.HeaderField{Name: ":colon", Value: "foo"})
1265 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
1269 func TestTransportInvalidTrailer_Capital1(t *testing.T) {
1270 testTransportInvalidTrailer_Capital(t, oneHeader)
1272 func TestTransportInvalidTrailer_Capital2(t *testing.T) {
1273 testTransportInvalidTrailer_Capital(t, splitHeader)
1275 func testTransportInvalidTrailer_Capital(t *testing.T, trailers headerType) {
1276 testInvalidTrailer(t, trailers, headerFieldNameError("Capital"), func(enc *hpack.Encoder) {
1277 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
1278 enc.WriteField(hpack.HeaderField{Name: "Capital", Value: "bad"})
1281 func TestTransportInvalidTrailer_EmptyFieldName(t *testing.T) {
1282 testInvalidTrailer(t, oneHeader, headerFieldNameError(""), func(enc *hpack.Encoder) {
1283 enc.WriteField(hpack.HeaderField{Name: "", Value: "bad"})
1286 func TestTransportInvalidTrailer_BinaryFieldValue(t *testing.T) {
1287 testInvalidTrailer(t, oneHeader, headerFieldValueError("has\nnewline"), func(enc *hpack.Encoder) {
1288 enc.WriteField(hpack.HeaderField{Name: "x", Value: "has\nnewline"})
1292 func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeTrailer func(*hpack.Encoder)) {
1293 ct := newClientTester(t)
1294 ct.client = func() error {
1295 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
1296 res, err := ct.tr.RoundTrip(req)
1298 return fmt.Errorf("RoundTrip: %v", err)
1300 defer res.Body.Close()
1301 if res.StatusCode != 200 {
1302 return fmt.Errorf("status code = %v; want 200", res.StatusCode)
1304 slurp, err := ioutil.ReadAll(res.Body)
1305 se, ok := err.(StreamError)
1306 if !ok || se.Cause != wantErr {
1307 return fmt.Errorf("res.Body ReadAll error = %q, %#v; want StreamError with cause %T, %#v", slurp, err, wantErr, wantErr)
1310 return fmt.Errorf("body = %q; want nothing", slurp)
1314 ct.server = func() error {
1316 var buf bytes.Buffer
1317 enc := hpack.NewEncoder(&buf)
1320 f, err := ct.fr.ReadFrame()
1324 switch f := f.(type) {
1327 send := func(mode headerType) {
1331 ct.fr.WriteHeaders(HeadersFrameParam{
1332 StreamID: f.StreamID,
1334 EndStream: endStream,
1341 ct.fr.WriteHeaders(HeadersFrameParam{
1342 StreamID: f.StreamID,
1344 EndStream: endStream,
1345 BlockFragment: hbf[:1],
1347 ct.fr.WriteContinuation(f.StreamID, true, hbf[1:])
1352 // Response headers (1+ frames; 1 or 2 in this test, but never 0)
1355 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1356 enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "declared"})
1374 // headerListSize returns the HTTP2 header list size of h.
1375 // http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE
1376 // http://httpwg.org/specs/rfc7540.html#MaxHeaderBlock
1377 func headerListSize(h http.Header) (size uint32) {
1378 for k, vv := range h {
1379 for _, v := range vv {
1380 hf := hpack.HeaderField{Name: k, Value: v}
1387 // padHeaders adds data to an http.Header until headerListSize(h) ==
1388 // limit. Due to the way header list sizes are calculated, padHeaders
1389 // cannot add fewer than len("Pad-Headers") + 32 bytes to h, and will
1390 // call t.Fatal if asked to do so. PadHeaders first reserves enough
1391 // space for an empty "Pad-Headers" key, then adds as many copies of
1392 // filler as possible. Any remaining bytes necessary to push the
1393 // header list size up to limit are added to h["Pad-Headers"].
1394 func padHeaders(t *testing.T, h http.Header, limit uint64, filler string) {
1395 if limit > 0xffffffff {
1396 t.Fatalf("padHeaders: refusing to pad to more than 2^32-1 bytes. limit = %v", limit)
1398 hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""}
1399 minPadding := uint64(hf.Size())
1400 size := uint64(headerListSize(h))
1402 minlimit := size + minPadding
1403 if limit < minlimit {
1404 t.Fatalf("padHeaders: limit %v < %v", limit, minlimit)
1407 // Use a fixed-width format for name so that fieldSize
1408 // remains constant.
1409 nameFmt := "Pad-Headers-%06d"
1410 hf = hpack.HeaderField{Name: fmt.Sprintf(nameFmt, 1), Value: filler}
1411 fieldSize := uint64(hf.Size())
1413 // Add as many complete filler values as possible, leaving
1414 // room for at least one empty "Pad-Headers" key.
1415 limit = limit - minPadding
1416 for i := 0; size+fieldSize < limit; i++ {
1417 name := fmt.Sprintf(nameFmt, i)
1422 // Add enough bytes to reach limit.
1423 remain := limit - size
1424 lastValue := strings.Repeat("*", int(remain))
1425 h.Add("Pad-Headers", lastValue)
1428 func TestPadHeaders(t *testing.T) {
1429 check := func(h http.Header, limit uint32, fillerLen int) {
1431 h = make(http.Header)
1433 filler := strings.Repeat("f", fillerLen)
1434 padHeaders(t, h, uint64(limit), filler)
1435 gotSize := headerListSize(h)
1436 if gotSize != limit {
1437 t.Errorf("Got size = %v; want %v", gotSize, limit)
1440 // Try all possible combinations for small fillerLen and limit.
1441 hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""}
1442 minLimit := hf.Size()
1443 for limit := minLimit; limit <= 128; limit++ {
1444 for fillerLen := 0; uint32(fillerLen) <= limit; fillerLen++ {
1445 check(nil, limit, fillerLen)
1449 // Try a few tests with larger limits, plus cumulative
1450 // tests. Since these tests are cumulative, tests[i+1].limit
1451 // must be >= tests[i].limit + minLimit. See the comment on
1452 // padHeaders for more info on why the limit arg has this
1479 h := make(http.Header)
1480 for _, tc := range tests {
1481 check(nil, tc.limit, tc.fillerLen)
1482 check(h, tc.limit, tc.fillerLen)
1486 func TestTransportChecksRequestHeaderListSize(t *testing.T) {
1487 st := newServerTester(t,
1488 func(w http.ResponseWriter, r *http.Request) {
1489 // Consume body & force client to send
1490 // trailers before writing response.
1491 // ioutil.ReadAll returns non-nil err for
1492 // requests that attempt to send greater than
1493 // maxHeaderListSize bytes of trailers, since
1494 // those requests generate a stream reset.
1495 ioutil.ReadAll(r.Body)
1498 func(ts *httptest.Server) {
1499 ts.Config.MaxHeaderBytes = 16 << 10
1506 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1507 defer tr.CloseIdleConnections()
1509 checkRoundTrip := func(req *http.Request, wantErr error, desc string) {
1510 res, err := tr.RoundTrip(req)
1515 t.Errorf("%v: RoundTrip err = %v; want %v", desc, err, wantErr)
1520 t.Errorf("%v: response nil; want non-nil.", desc)
1523 defer res.Body.Close()
1524 if res.StatusCode != http.StatusOK {
1525 t.Errorf("%v: response status = %v; want %v", desc, res.StatusCode, http.StatusOK)
1530 t.Errorf("%v: RoundTrip err = %v but response non-nil", desc, err)
1533 headerListSizeForRequest := func(req *http.Request) (size uint64) {
1534 contentLen := actualContentLength(req)
1535 trailers, err := commaSeparatedTrailers(req)
1537 t.Fatalf("headerListSizeForRequest: %v", err)
1539 cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
1540 cc.henc = hpack.NewEncoder(&cc.hbuf)
1542 hdrs, err := cc.encodeHeaders(req, true, trailers, contentLen)
1545 t.Fatalf("headerListSizeForRequest: %v", err)
1547 hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(hf hpack.HeaderField) {
1548 size += uint64(hf.Size())
1551 if _, err := hpackDec.Write(hdrs); err != nil {
1552 t.Fatalf("headerListSizeForRequest: %v", err)
1557 // Create a new Request for each test, rather than reusing the
1558 // same Request, to avoid a race when modifying req.Headers.
1559 // See https://github.com/golang/go/issues/21316
1560 newRequest := func() *http.Request {
1561 // Body must be non-nil to enable writing trailers.
1562 body := strings.NewReader("hello")
1563 req, err := http.NewRequest("POST", st.ts.URL, body)
1565 t.Fatalf("newRequest: NewRequest: %v", err)
1570 // Make an arbitrary request to ensure we get the server's
1571 // settings frame and initialize peerMaxHeaderListSize.
1573 checkRoundTrip(req, nil, "Initial request")
1575 // Get the ClientConn associated with the request and validate
1576 // peerMaxHeaderListSize.
1577 addr := authorityAddr(req.URL.Scheme, req.URL.Host)
1578 cc, err := tr.connPool().GetClientConn(req, addr)
1580 t.Fatalf("GetClientConn: %v", err)
1583 peerSize := cc.peerMaxHeaderListSize
1586 wantSize := uint64(st.sc.maxHeaderListSize())
1588 if peerSize != wantSize {
1589 t.Errorf("peerMaxHeaderListSize = %v; want %v", peerSize, wantSize)
1592 // Sanity check peerSize. (*serverConn) maxHeaderListSize adds
1593 // 320 bytes of padding.
1594 wantHeaderBytes := uint64(st.ts.Config.MaxHeaderBytes) + 320
1595 if peerSize != wantHeaderBytes {
1596 t.Errorf("peerMaxHeaderListSize = %v; want %v.", peerSize, wantHeaderBytes)
1599 // Pad headers & trailers, but stay under peerSize.
1601 req.Header = make(http.Header)
1602 req.Trailer = make(http.Header)
1603 filler := strings.Repeat("*", 1024)
1604 padHeaders(t, req.Trailer, peerSize, filler)
1605 // cc.encodeHeaders adds some default headers to the request,
1606 // so we need to leave room for those.
1607 defaultBytes := headerListSizeForRequest(req)
1608 padHeaders(t, req.Header, peerSize-defaultBytes, filler)
1609 checkRoundTrip(req, nil, "Headers & Trailers under limit")
1611 // Add enough header bytes to push us over peerSize.
1613 req.Header = make(http.Header)
1614 padHeaders(t, req.Header, peerSize, filler)
1615 checkRoundTrip(req, errRequestHeaderListSize, "Headers over limit")
1617 // Push trailers over the limit.
1619 req.Trailer = make(http.Header)
1620 padHeaders(t, req.Trailer, peerSize+1, filler)
1621 checkRoundTrip(req, errRequestHeaderListSize, "Trailers over limit")
1623 // Send headers with a single large value.
1625 filler = strings.Repeat("*", int(peerSize))
1626 req.Header = make(http.Header)
1627 req.Header.Set("Big", filler)
1628 checkRoundTrip(req, errRequestHeaderListSize, "Single large header")
1630 // Send trailers with a single large value.
1632 req.Trailer = make(http.Header)
1633 req.Trailer.Set("Big", filler)
1634 checkRoundTrip(req, errRequestHeaderListSize, "Single large trailer")
1637 func TestTransportChecksResponseHeaderListSize(t *testing.T) {
1638 ct := newClientTester(t)
1639 ct.client = func() error {
1640 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
1641 res, err := ct.tr.RoundTrip(req)
1642 if err != errResponseHeaderListSize {
1647 for k, vv := range res.Header {
1648 for _, v := range vv {
1649 size += int64(len(k)) + int64(len(v)) + 32
1652 return fmt.Errorf("RoundTrip Error = %v (and %d bytes of response headers); want errResponseHeaderListSize", err, size)
1656 ct.server = func() error {
1658 var buf bytes.Buffer
1659 enc := hpack.NewEncoder(&buf)
1662 f, err := ct.fr.ReadFrame()
1666 switch f := f.(type) {
1668 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1669 large := strings.Repeat("a", 1<<10)
1670 for i := 0; i < 5042; i++ {
1671 enc.WriteField(hpack.HeaderField{Name: large, Value: large})
1673 if size, want := buf.Len(), 6329; size != want {
1674 // Note: this number might change if
1675 // our hpack implementation
1676 // changes. That's fine. This is
1677 // just a sanity check that our
1678 // response can fit in a single
1679 // header block fragment frame.
1680 return fmt.Errorf("encoding over 10MB of duplicate keypairs took %d bytes; expected %d", size, want)
1682 ct.fr.WriteHeaders(HeadersFrameParam{
1683 StreamID: f.StreamID,
1686 BlockFragment: buf.Bytes(),
1695 // Test that the the Transport returns a typed error from Response.Body.Read calls
1696 // when the server sends an error. (here we use a panic, since that should generate
1697 // a stream error, but others like cancel should be similar)
1698 func TestTransportBodyReadErrorType(t *testing.T) {
1699 doPanic := make(chan bool, 1)
1700 st := newServerTester(t,
1701 func(w http.ResponseWriter, r *http.Request) {
1702 w.(http.Flusher).Flush() // force headers out
1711 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1712 defer tr.CloseIdleConnections()
1713 c := &http.Client{Transport: tr}
1715 res, err := c.Get(st.ts.URL)
1719 defer res.Body.Close()
1721 buf := make([]byte, 100)
1722 n, err := res.Body.Read(buf)
1723 want := StreamError{StreamID: 0x1, Code: 0x2}
1724 if !reflect.DeepEqual(want, err) {
1725 t.Errorf("Read = %v, %#v; want error %#v", n, err, want)
1729 // golang.org/issue/13924
1730 // This used to fail after many iterations, especially with -race:
1731 // go test -v -run=TestTransportDoubleCloseOnWriteError -count=500 -race
1732 func TestTransportDoubleCloseOnWriteError(t *testing.T) {
1735 conn net.Conn // to close if set
1738 st := newServerTester(t,
1739 func(w http.ResponseWriter, r *http.Request) {
1751 TLSClientConfig: tlsConfigInsecure,
1752 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
1753 tc, err := tls.Dial(network, addr, cfg)
1763 defer tr.CloseIdleConnections()
1764 c := &http.Client{Transport: tr}
1768 // Test that the http1 Transport.DisableKeepAlives option is respected
1769 // and connections are closed as soon as idle.
1770 // See golang.org/issue/14008
1771 func TestTransportDisableKeepAlives(t *testing.T) {
1772 st := newServerTester(t,
1773 func(w http.ResponseWriter, r *http.Request) {
1774 io.WriteString(w, "hi")
1780 connClosed := make(chan struct{}) // closed on tls.Conn.Close
1782 t1: &http.Transport{
1783 DisableKeepAlives: true,
1785 TLSClientConfig: tlsConfigInsecure,
1786 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
1787 tc, err := tls.Dial(network, addr, cfg)
1791 return ¬eCloseConn{Conn: tc, closefn: func() { close(connClosed) }}, nil
1794 c := &http.Client{Transport: tr}
1795 res, err := c.Get(st.ts.URL)
1799 if _, err := ioutil.ReadAll(res.Body); err != nil {
1802 defer res.Body.Close()
1806 case <-time.After(1 * time.Second):
1812 // Test concurrent requests with Transport.DisableKeepAlives. We can share connections,
1813 // but when things are totally idle, it still needs to close.
1814 func TestTransportDisableKeepAlives_Concurrency(t *testing.T) {
1815 const D = 25 * time.Millisecond
1816 st := newServerTester(t,
1817 func(w http.ResponseWriter, r *http.Request) {
1819 io.WriteString(w, "hi")
1826 var conns sync.WaitGroup
1828 t1: &http.Transport{
1829 DisableKeepAlives: true,
1831 TLSClientConfig: tlsConfigInsecure,
1832 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
1833 tc, err := tls.Dial(network, addr, cfg)
1837 atomic.AddInt32(&dials, 1)
1839 return ¬eCloseConn{Conn: tc, closefn: func() { conns.Done() }}, nil
1842 c := &http.Client{Transport: tr}
1843 var reqs sync.WaitGroup
1845 for i := 0; i < N; i++ {
1848 // For the final request, try to make all the
1849 // others close. This isn't verified in the
1850 // count, other than the Log statement, since
1851 // it's so timing dependent. This test is
1852 // really to make sure we don't interrupt a
1858 res, err := c.Get(st.ts.URL)
1863 if _, err := ioutil.ReadAll(res.Body); err != nil {
1872 t.Logf("did %d dials, %d requests", atomic.LoadInt32(&dials), N)
1875 type noteCloseConn struct {
1881 func (c *noteCloseConn) Close() error {
1882 c.onceClose.Do(c.closefn)
1883 return c.Conn.Close()
1886 func isTimeout(err error) bool {
1887 switch err := err.(type) {
1891 return isTimeout(err.Err)
1893 return err.Timeout()
1898 // Test that the http1 Transport.ResponseHeaderTimeout option and cancel is sent.
1899 func TestTransportResponseHeaderTimeout_NoBody(t *testing.T) {
1900 testTransportResponseHeaderTimeout(t, false)
1902 func TestTransportResponseHeaderTimeout_Body(t *testing.T) {
1903 testTransportResponseHeaderTimeout(t, true)
1906 func testTransportResponseHeaderTimeout(t *testing.T, body bool) {
1907 ct := newClientTester(t)
1908 ct.tr.t1 = &http.Transport{
1909 ResponseHeaderTimeout: 5 * time.Millisecond,
1911 ct.client = func() error {
1912 c := &http.Client{Transport: ct.tr}
1915 const bodySize = 4 << 20
1917 _, err = c.Post("https://dummy.tld/", "text/foo", io.LimitReader(countingReader{&n}, bodySize))
1919 _, err = c.Get("https://dummy.tld/")
1921 if !isTimeout(err) {
1922 t.Errorf("client expected timeout error; got %#v", err)
1924 if body && n != bodySize {
1925 t.Errorf("only read %d bytes of body; want %d", n, bodySize)
1929 ct.server = func() error {
1932 f, err := ct.fr.ReadFrame()
1934 t.Logf("ReadFrame: %v", err)
1937 switch f := f.(type) {
1939 dataLen := len(f.Data())
1941 if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
1944 if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
1948 case *RSTStreamFrame:
1949 if f.StreamID == 1 && f.ErrCode == ErrCodeCancel {
1958 func TestTransportDisableCompression(t *testing.T) {
1960 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1961 want := http.Header{
1962 "User-Agent": []string{"Go-http-client/2.0"},
1964 if !reflect.DeepEqual(r.Header, want) {
1965 t.Errorf("request headers = %v; want %v", r.Header, want)
1971 TLSClientConfig: tlsConfigInsecure,
1972 t1: &http.Transport{
1973 DisableCompression: true,
1976 defer tr.CloseIdleConnections()
1978 req, err := http.NewRequest("GET", st.ts.URL, nil)
1982 res, err := tr.RoundTrip(req)
1986 defer res.Body.Close()
1989 // RFC 7540 section 8.1.2.2
1990 func TestTransportRejectsConnHeaders(t *testing.T) {
1991 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1993 for k := range r.Header {
1994 got = append(got, k)
1997 w.Header().Set("Got-Header", strings.Join(got, ","))
2001 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
2002 defer tr.CloseIdleConnections()
2011 value: []string{"anything"},
2012 want: "ERROR: http2: invalid Upgrade request header: [\"anything\"]",
2016 value: []string{"foo"},
2017 want: "ERROR: http2: invalid Connection request header: [\"foo\"]",
2021 value: []string{"close"},
2022 want: "Accept-Encoding,User-Agent",
2026 value: []string{"close", "something-else"},
2027 want: "ERROR: http2: invalid Connection request header: [\"close\" \"something-else\"]",
2031 value: []string{"keep-alive"},
2032 want: "Accept-Encoding,User-Agent",
2035 key: "Proxy-Connection", // just deleted and ignored
2036 value: []string{"keep-alive"},
2037 want: "Accept-Encoding,User-Agent",
2040 key: "Transfer-Encoding",
2041 value: []string{""},
2042 want: "Accept-Encoding,User-Agent",
2045 key: "Transfer-Encoding",
2046 value: []string{"foo"},
2047 want: "ERROR: http2: invalid Transfer-Encoding request header: [\"foo\"]",
2050 key: "Transfer-Encoding",
2051 value: []string{"chunked"},
2052 want: "Accept-Encoding,User-Agent",
2055 key: "Transfer-Encoding",
2056 value: []string{"chunked", "other"},
2057 want: "ERROR: http2: invalid Transfer-Encoding request header: [\"chunked\" \"other\"]",
2060 key: "Content-Length",
2061 value: []string{"123"},
2062 want: "Accept-Encoding,User-Agent",
2066 value: []string{"doop"},
2067 want: "Accept-Encoding,User-Agent",
2071 for _, tt := range tests {
2072 req, _ := http.NewRequest("GET", st.ts.URL, nil)
2073 req.Header[tt.key] = tt.value
2074 res, err := tr.RoundTrip(req)
2077 got = fmt.Sprintf("ERROR: %v", err)
2079 got = res.Header.Get("Got-Header")
2083 t.Errorf("For key %q, value %q, got = %q; want %q", tt.key, tt.value, got, tt.want)
2088 // golang.org/issue/14048
2089 func TestTransportFailsOnInvalidHeaders(t *testing.T) {
2090 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
2092 for k := range r.Header {
2093 got = append(got, k)
2096 w.Header().Set("Got-Header", strings.Join(got, ","))
2100 tests := [...]struct {
2105 h: http.Header{"with space": {"foo"}},
2106 wantErr: `invalid HTTP header name "with space"`,
2109 h: http.Header{"name": {"Брэд"}},
2110 wantErr: "", // okay
2113 h: http.Header{"имя": {"Brad"}},
2114 wantErr: `invalid HTTP header name "имя"`,
2117 h: http.Header{"foo": {"foo\x01bar"}},
2118 wantErr: `invalid HTTP header value "foo\x01bar" for header "foo"`,
2122 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
2123 defer tr.CloseIdleConnections()
2125 for i, tt := range tests {
2126 req, _ := http.NewRequest("GET", st.ts.URL, nil)
2128 res, err := tr.RoundTrip(req)
2130 if tt.wantErr == "" {
2133 t.Errorf("case %d: error = %v; want no error", i, err)
2136 if !strings.Contains(fmt.Sprint(err), tt.wantErr) {
2138 t.Errorf("case %d: error = %v; want error %q", i, err, tt.wantErr)
2143 t.Logf("case %d: server got headers %q", i, res.Header.Get("Got-Header"))
2150 // Tests that gzipReader doesn't crash on a second Read call following
2151 // the first Read call's gzip.NewReader returning an error.
2152 func TestGzipReader_DoubleReadCrash(t *testing.T) {
2154 body: ioutil.NopCloser(strings.NewReader("0123456789")),
2157 n, err1 := gz.Read(buf[:])
2158 if n != 0 || !strings.Contains(fmt.Sprint(err1), "invalid header") {
2159 t.Fatalf("Read = %v, %v; want 0, invalid header", n, err1)
2161 n, err2 := gz.Read(buf[:])
2162 if n != 0 || err2 != err1 {
2163 t.Fatalf("second Read = %v, %v; want 0, %v", n, err2, err1)
2167 func TestTransportNewTLSConfig(t *testing.T) {
2168 tests := [...]struct {
2178 ServerName: "foo.com",
2179 NextProtos: []string{NextProtoTLS},
2183 // User-provided name (bar.com) takes precedence:
2186 ServerName: "bar.com",
2190 ServerName: "bar.com",
2191 NextProtos: []string{NextProtoTLS},
2195 // NextProto is prepended:
2198 NextProtos: []string{"foo", "bar"},
2200 host: "example.com",
2202 ServerName: "example.com",
2203 NextProtos: []string{NextProtoTLS, "foo", "bar"},
2207 // NextProto is not duplicated:
2210 NextProtos: []string{"foo", "bar", NextProtoTLS},
2212 host: "example.com",
2214 ServerName: "example.com",
2215 NextProtos: []string{"foo", "bar", NextProtoTLS},
2219 for i, tt := range tests {
2220 // Ignore the session ticket keys part, which ends up populating
2221 // unexported fields in the Config:
2223 tt.conf.SessionTicketsDisabled = true
2226 tr := &Transport{TLSClientConfig: tt.conf}
2227 got := tr.newTLSConfig(tt.host)
2229 got.SessionTicketsDisabled = false
2231 if !reflect.DeepEqual(got, tt.want) {
2232 t.Errorf("%d. got %#v; want %#v", i, got, tt.want)
2237 // The Google GFE responds to HEAD requests with a HEADERS frame
2238 // without END_STREAM, followed by a 0-length DATA frame with
2239 // END_STREAM. Make sure we don't get confused by that. (We did.)
2240 func TestTransportReadHeadResponse(t *testing.T) {
2241 ct := newClientTester(t)
2242 clientDone := make(chan struct{})
2243 ct.client = func() error {
2244 defer close(clientDone)
2245 req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
2246 res, err := ct.tr.RoundTrip(req)
2250 if res.ContentLength != 123 {
2251 return fmt.Errorf("Content-Length = %d; want 123", res.ContentLength)
2253 slurp, err := ioutil.ReadAll(res.Body)
2255 return fmt.Errorf("ReadAll: %v", err)
2258 return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
2262 ct.server = func() error {
2265 f, err := ct.fr.ReadFrame()
2267 t.Logf("ReadFrame: %v", err)
2270 hf, ok := f.(*HeadersFrame)
2274 var buf bytes.Buffer
2275 enc := hpack.NewEncoder(&buf)
2276 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2277 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
2278 ct.fr.WriteHeaders(HeadersFrameParam{
2279 StreamID: hf.StreamID,
2281 EndStream: false, // as the GFE does
2282 BlockFragment: buf.Bytes(),
2284 ct.fr.WriteData(hf.StreamID, true, nil)
2293 type neverEnding byte
2295 func (b neverEnding) Read(p []byte) (int, error) {
2302 // golang.org/issue/15425: test that a handler closing the request
2303 // body doesn't terminate the stream to the peer. (It just stops
2304 // readability from the handler's side, and eventually the client
2305 // runs out of flow control tokens)
2306 func TestTransportHandlerBodyClose(t *testing.T) {
2307 const bodySize = 10 << 20
2308 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
2310 io.Copy(w, io.LimitReader(neverEnding('A'), bodySize))
2314 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
2315 defer tr.CloseIdleConnections()
2317 g0 := runtime.NumGoroutine()
2320 for i := 0; i < numReq; i++ {
2321 req, err := http.NewRequest("POST", st.ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
2325 res, err := tr.RoundTrip(req)
2329 n, err := io.Copy(ioutil.Discard, res.Body)
2331 if n != bodySize || err != nil {
2332 t.Fatalf("req#%d: Copy = %d, %v; want %d, nil", i, n, err, bodySize)
2335 tr.CloseIdleConnections()
2337 gd := runtime.NumGoroutine() - g0
2339 t.Errorf("appeared to leak goroutines")
2344 // https://golang.org/issue/15930
2345 func TestTransportFlowControl(t *testing.T) {
2346 const bufLen = 64 << 10
2347 var total int64 = 100 << 20 // 100MB
2348 if testing.Short() {
2352 var wrote int64 // updated atomically
2353 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
2354 b := make([]byte, bufLen)
2356 n, err := w.Write(b)
2357 atomic.AddInt64(&wrote, int64(n))
2359 t.Errorf("ResponseWriter.Write error: %v", err)
2362 w.(http.Flusher).Flush()
2366 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
2367 defer tr.CloseIdleConnections()
2368 req, err := http.NewRequest("GET", st.ts.URL, nil)
2370 t.Fatal("NewRequest error:", err)
2372 resp, err := tr.RoundTrip(req)
2374 t.Fatal("RoundTrip error:", err)
2376 defer resp.Body.Close()
2379 b := make([]byte, bufLen)
2381 n, err := resp.Body.Read(b)
2386 t.Fatal("Read error:", err)
2390 const max = transportDefaultStreamFlow
2391 if w := atomic.LoadInt64(&wrote); -max > read-w || read-w > max {
2392 t.Fatalf("Too much data inflight: server wrote %v bytes but client only received %v", w, read)
2395 // Let the server get ahead of the client.
2396 time.Sleep(1 * time.Millisecond)
2400 // golang.org/issue/14627 -- if the server sends a GOAWAY frame, make
2401 // the Transport remember it and return it back to users (via
2402 // RoundTrip or request body reads) if needed (e.g. if the server
2403 // proceeds to close the TCP connection before the client gets its
2405 func TestTransportUsesGoAwayDebugError_RoundTrip(t *testing.T) {
2406 testTransportUsesGoAwayDebugError(t, false)
2409 func TestTransportUsesGoAwayDebugError_Body(t *testing.T) {
2410 testTransportUsesGoAwayDebugError(t, true)
2413 func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) {
2414 ct := newClientTester(t)
2415 clientDone := make(chan struct{})
2417 const goAwayErrCode = ErrCodeHTTP11Required // arbitrary
2418 const goAwayDebugData = "some debug data"
2420 ct.client = func() error {
2421 defer close(clientDone)
2422 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2423 res, err := ct.tr.RoundTrip(req)
2426 return fmt.Errorf("unexpected client RoundTrip error: %v", err)
2428 _, err = io.Copy(ioutil.Discard, res.Body)
2431 want := GoAwayError{
2433 ErrCode: goAwayErrCode,
2434 DebugData: goAwayDebugData,
2436 if !reflect.DeepEqual(err, want) {
2437 t.Errorf("RoundTrip error = %T: %#v, want %T (%#v)", err, err, want, want)
2441 ct.server = func() error {
2444 f, err := ct.fr.ReadFrame()
2446 t.Logf("ReadFrame: %v", err)
2449 hf, ok := f.(*HeadersFrame)
2454 var buf bytes.Buffer
2455 enc := hpack.NewEncoder(&buf)
2456 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2457 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
2458 ct.fr.WriteHeaders(HeadersFrameParam{
2459 StreamID: hf.StreamID,
2462 BlockFragment: buf.Bytes(),
2465 // Write two GOAWAY frames, to test that the Transport takes
2466 // the interesting parts of both.
2467 ct.fr.WriteGoAway(5, ErrCodeNo, []byte(goAwayDebugData))
2468 ct.fr.WriteGoAway(5, goAwayErrCode, nil)
2469 ct.sc.(*net.TCPConn).CloseWrite()
2477 func testTransportReturnsUnusedFlowControl(t *testing.T, oneDataFrame bool) {
2478 ct := newClientTester(t)
2480 clientClosed := make(chan struct{})
2481 serverWroteFirstByte := make(chan struct{})
2483 ct.client = func() error {
2484 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2485 res, err := ct.tr.RoundTrip(req)
2489 <-serverWroteFirstByte
2491 if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 {
2492 return fmt.Errorf("body read = %v, %v; want 1, nil", n, err)
2494 res.Body.Close() // leaving 4999 bytes unread
2499 ct.server = func() error {
2502 var hf *HeadersFrame
2504 f, err := ct.fr.ReadFrame()
2506 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
2509 case *WindowUpdateFrame, *SettingsFrame:
2513 hf, ok = f.(*HeadersFrame)
2515 return fmt.Errorf("Got %T; want HeadersFrame", f)
2520 var buf bytes.Buffer
2521 enc := hpack.NewEncoder(&buf)
2522 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2523 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"})
2524 ct.fr.WriteHeaders(HeadersFrameParam{
2525 StreamID: hf.StreamID,
2528 BlockFragment: buf.Bytes(),
2532 // - Send one DATA frame with 5000 bytes.
2533 // - Send two DATA frames with 1 and 4999 bytes each.
2535 // In both cases, the client should consume one byte of data,
2536 // refund that byte, then refund the following 4999 bytes.
2538 // In the second case, the server waits for the client connection to
2539 // close before seconding the second DATA frame. This tests the case
2540 // where the client receives a DATA frame after it has reset the stream.
2542 ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 5000))
2543 close(serverWroteFirstByte)
2546 ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 1))
2547 close(serverWroteFirstByte)
2549 ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 4999))
2552 waitingFor := "RSTStreamFrame"
2554 f, err := ct.fr.ReadFrame()
2556 return fmt.Errorf("ReadFrame while waiting for %s: %v", waitingFor, err)
2558 if _, ok := f.(*SettingsFrame); ok {
2562 case "RSTStreamFrame":
2563 if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel {
2564 return fmt.Errorf("Expected a RSTStreamFrame with code cancel; got %v", summarizeFrame(f))
2566 waitingFor = "WindowUpdateFrame"
2567 case "WindowUpdateFrame":
2568 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != 4999 {
2569 return fmt.Errorf("Expected WindowUpdateFrame for 4999 bytes; got %v", summarizeFrame(f))
2578 // See golang.org/issue/16481
2579 func TestTransportReturnsUnusedFlowControlSingleWrite(t *testing.T) {
2580 testTransportReturnsUnusedFlowControl(t, true)
2583 // See golang.org/issue/20469
2584 func TestTransportReturnsUnusedFlowControlMultipleWrites(t *testing.T) {
2585 testTransportReturnsUnusedFlowControl(t, false)
2588 // Issue 16612: adjust flow control on open streams when transport
2589 // receives SETTINGS with INITIAL_WINDOW_SIZE from server.
2590 func TestTransportAdjustsFlowControl(t *testing.T) {
2591 ct := newClientTester(t)
2592 clientDone := make(chan struct{})
2594 const bodySize = 1 << 20
2596 ct.client = func() error {
2597 defer ct.cc.(*net.TCPConn).CloseWrite()
2598 defer close(clientDone)
2600 req, _ := http.NewRequest("POST", "https://dummy.tld/", struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
2601 res, err := ct.tr.RoundTrip(req)
2608 ct.server = func() error {
2609 _, err := io.ReadFull(ct.sc, make([]byte, len(ClientPreface)))
2611 return fmt.Errorf("reading client preface: %v", err)
2615 var sentSettings bool
2617 f, err := ct.fr.ReadFrame()
2623 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
2626 switch f := f.(type) {
2628 gotBytes += int64(len(f.Data()))
2629 // After we've got half the client's
2630 // initial flow control window's worth
2631 // of request body data, give it just
2632 // enough flow control to finish.
2633 if gotBytes >= initialWindowSize/2 && !sentSettings {
2636 ct.fr.WriteSettings(Setting{ID: SettingInitialWindowSize, Val: bodySize})
2637 ct.fr.WriteWindowUpdate(0, bodySize)
2638 ct.fr.WriteSettingsAck()
2641 if f.StreamEnded() {
2642 var buf bytes.Buffer
2643 enc := hpack.NewEncoder(&buf)
2644 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2645 ct.fr.WriteHeaders(HeadersFrameParam{
2646 StreamID: f.StreamID,
2649 BlockFragment: buf.Bytes(),
2658 // See golang.org/issue/16556
2659 func TestTransportReturnsDataPaddingFlowControl(t *testing.T) {
2660 ct := newClientTester(t)
2662 unblockClient := make(chan bool, 1)
2664 ct.client = func() error {
2665 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2666 res, err := ct.tr.RoundTrip(req)
2670 defer res.Body.Close()
2674 ct.server = func() error {
2677 var hf *HeadersFrame
2679 f, err := ct.fr.ReadFrame()
2681 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
2684 case *WindowUpdateFrame, *SettingsFrame:
2688 hf, ok = f.(*HeadersFrame)
2690 return fmt.Errorf("Got %T; want HeadersFrame", f)
2695 var buf bytes.Buffer
2696 enc := hpack.NewEncoder(&buf)
2697 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2698 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"})
2699 ct.fr.WriteHeaders(HeadersFrameParam{
2700 StreamID: hf.StreamID,
2703 BlockFragment: buf.Bytes(),
2705 pad := make([]byte, 5)
2706 ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream
2708 f, err := ct.readNonSettingsFrame()
2710 return fmt.Errorf("ReadFrame while waiting for first WindowUpdateFrame: %v", err)
2712 wantBack := uint32(len(pad)) + 1 // one byte for the length of the padding
2713 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID != 0 {
2714 return fmt.Errorf("Expected conn WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f))
2717 f, err = ct.readNonSettingsFrame()
2719 return fmt.Errorf("ReadFrame while waiting for second WindowUpdateFrame: %v", err)
2721 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID == 0 {
2722 return fmt.Errorf("Expected stream WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f))
2724 unblockClient <- true
2730 // golang.org/issue/16572 -- RoundTrip shouldn't hang when it gets a
2731 // StreamError as a result of the response HEADERS
2732 func TestTransportReturnsErrorOnBadResponseHeaders(t *testing.T) {
2733 ct := newClientTester(t)
2735 ct.client = func() error {
2736 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2737 res, err := ct.tr.RoundTrip(req)
2740 return errors.New("unexpected successful GET")
2742 want := StreamError{1, ErrCodeProtocol, headerFieldNameError(" content-type")}
2743 if !reflect.DeepEqual(want, err) {
2744 t.Errorf("RoundTrip error = %#v; want %#v", err, want)
2748 ct.server = func() error {
2751 hf, err := ct.firstHeaders()
2756 var buf bytes.Buffer
2757 enc := hpack.NewEncoder(&buf)
2758 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2759 enc.WriteField(hpack.HeaderField{Name: " content-type", Value: "bogus"}) // bogus spaces
2760 ct.fr.WriteHeaders(HeadersFrameParam{
2761 StreamID: hf.StreamID,
2764 BlockFragment: buf.Bytes(),
2768 fr, err := ct.readFrame()
2770 return fmt.Errorf("error waiting for RST_STREAM from client: %v", err)
2772 if _, ok := fr.(*SettingsFrame); ok {
2775 if rst, ok := fr.(*RSTStreamFrame); !ok || rst.StreamID != 1 || rst.ErrCode != ErrCodeProtocol {
2776 t.Errorf("Frame = %v; want RST_STREAM for stream 1 with ErrCodeProtocol", summarizeFrame(fr))
2786 // byteAndEOFReader returns is in an io.Reader which reads one byte
2787 // (the underlying byte) and io.EOF at once in its Read call.
2788 type byteAndEOFReader byte
2790 func (b byteAndEOFReader) Read(p []byte) (n int, err error) {
2792 panic("unexpected useless call")
2798 // Issue 16788: the Transport had a regression where it started
2799 // sending a spurious DATA frame with a duplicate END_STREAM bit after
2800 // the request body writer goroutine had already read an EOF from the
2801 // Request.Body and included the END_STREAM on a data-carrying DATA
2804 // Notably, to trigger this, the requests need to use a Request.Body
2805 // which returns (non-0, io.EOF) and also needs to set the ContentLength
2807 func TestTransportBodyDoubleEndStream(t *testing.T) {
2808 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
2813 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
2814 defer tr.CloseIdleConnections()
2816 for i := 0; i < 2; i++ {
2817 req, _ := http.NewRequest("POST", st.ts.URL, byteAndEOFReader('a'))
2818 req.ContentLength = 1
2819 res, err := tr.RoundTrip(req)
2821 t.Fatalf("failure on req %d: %v", i+1, err)
2823 defer res.Body.Close()
2827 // golang.org/issue/16847, golang.org/issue/19103
2828 func TestTransportRequestPathPseudo(t *testing.T) {
2829 type result struct {
2845 want: result{path: "/foo"},
2847 // In Go 1.7, we accepted paths of "//foo".
2848 // In Go 1.8, we rejected it (issue 16847).
2849 // In Go 1.9, we accepted it again (issue 19103).
2858 want: result{path: "//foo"},
2861 // Opaque with //$Matching_Hostname/path
2867 Opaque: "//foo.com/path",
2872 want: result{path: "/path"},
2875 // Opaque with some other Request.Host instead:
2882 Opaque: "//bar.com/path",
2887 want: result{path: "/path"},
2890 // Opaque without the leading "//":
2900 want: result{path: "/path"},
2903 // Opaque we can't handle:
2909 Opaque: "//unknown_host/path",
2914 want: result{err: `invalid request :path "https://unknown_host/path" from URL.Opaque = "//unknown_host/path"`},
2917 // A CONNECT request:
2928 for i, tt := range tests {
2929 cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
2930 cc.henc = hpack.NewEncoder(&cc.hbuf)
2932 hdrs, err := cc.encodeHeaders(tt.req, false, "", -1)
2935 hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(f hpack.HeaderField) {
2936 if f.Name == ":path" {
2941 got.err = err.Error()
2942 } else if len(hdrs) > 0 {
2943 if _, err := hpackDec.Write(hdrs); err != nil {
2944 t.Errorf("%d. bogus hpack: %v", i, err)
2949 t.Errorf("%d. got %+v; want %+v", i, got, tt.want)
2956 // golang.org/issue/17071 -- don't sniff the first byte of the request body
2957 // before we've determined that the ClientConn is usable.
2958 func TestRoundTripDoesntConsumeRequestBodyEarly(t *testing.T) {
2960 req, _ := http.NewRequest("POST", "http://foo.com/", ioutil.NopCloser(strings.NewReader(body)))
2964 _, err := cc.RoundTrip(req)
2965 if err != errClientConnUnusable {
2966 t.Fatalf("RoundTrip = %v; want errClientConnUnusable", err)
2968 slurp, err := ioutil.ReadAll(req.Body)
2970 t.Errorf("ReadAll = %v", err)
2972 if string(slurp) != body {
2973 t.Errorf("Body = %q; want %q", slurp, body)
2977 func TestClientConnPing(t *testing.T) {
2978 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer)
2980 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
2981 defer tr.CloseIdleConnections()
2982 cc, err := tr.dialClientConn(st.ts.Listener.Addr().String(), false)
2986 if err = cc.Ping(testContext{}); err != nil {
2991 // Issue 16974: if the server sent a DATA frame after the user
2992 // canceled the Transport's Request, the Transport previously wrote to a
2993 // closed pipe, got an error, and ended up closing the whole TCP
2995 func TestTransportCancelDataResponseRace(t *testing.T) {
2996 cancel := make(chan struct{})
2997 clientGotError := make(chan bool, 1)
2999 const msg = "Hello."
3000 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
3001 if strings.Contains(r.URL.Path, "/hello") {
3002 time.Sleep(50 * time.Millisecond)
3003 io.WriteString(w, msg)
3006 for i := 0; i < 50; i++ {
3007 io.WriteString(w, "Some data.")
3008 w.(http.Flusher).Flush()
3013 time.Sleep(10 * time.Millisecond)
3018 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
3019 defer tr.CloseIdleConnections()
3021 c := &http.Client{Transport: tr}
3022 req, _ := http.NewRequest("GET", st.ts.URL, nil)
3024 res, err := c.Do(req)
3028 if _, err = io.Copy(ioutil.Discard, res.Body); err == nil {
3029 t.Fatal("unexpected success")
3031 clientGotError <- true
3033 res, err = c.Get(st.ts.URL + "/hello")
3037 slurp, err := ioutil.ReadAll(res.Body)
3041 if string(slurp) != msg {
3042 t.Errorf("Got = %q; want %q", slurp, msg)
3046 func TestTransportRetryAfterGOAWAY(t *testing.T) {
3051 ct1 := make(chan *clientTester)
3052 ct2 := make(chan *clientTester)
3054 ln := newLocalListener(t)
3058 TLSClientConfig: tlsConfigInsecure,
3060 tr.DialTLS = func(network, addr string, cfg *tls.Config) (net.Conn, error) {
3062 defer dialer.Unlock()
3064 if dialer.count == 3 {
3065 return nil, errors.New("unexpected number of dials")
3067 cc, err := net.Dial("tcp", ln.Addr().String())
3069 return nil, fmt.Errorf("dial error: %v", err)
3071 sc, err := ln.Accept()
3073 return nil, fmt.Errorf("accept error: %v", err)
3075 ct := &clientTester{
3080 fr: NewFramer(sc, sc),
3082 switch dialer.count {
3091 errs := make(chan error, 3)
3092 done := make(chan struct{})
3097 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
3098 res, err := tr.RoundTrip(req)
3101 if got := res.Header.Get("Foo"); got != "bar" {
3102 err = fmt.Errorf("foo header = %q; want bar", got)
3106 err = fmt.Errorf("RoundTrip: %v", err)
3111 connToClose := make(chan io.Closer, 2)
3113 // Server for the first request.
3115 var ct *clientTester
3122 connToClose <- ct.cc
3124 hf, err := ct.firstHeaders()
3126 errs <- fmt.Errorf("server1 failed reading HEADERS: %v", err)
3129 t.Logf("server1 got %v", hf)
3130 if err := ct.fr.WriteGoAway(0 /*max id*/, ErrCodeNo, nil); err != nil {
3131 errs <- fmt.Errorf("server1 failed writing GOAWAY: %v", err)
3137 // Server for the second request.
3139 var ct *clientTester
3146 connToClose <- ct.cc
3148 hf, err := ct.firstHeaders()
3150 errs <- fmt.Errorf("server2 failed reading HEADERS: %v", err)
3153 t.Logf("server2 got %v", hf)
3155 var buf bytes.Buffer
3156 enc := hpack.NewEncoder(&buf)
3157 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
3158 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
3159 err = ct.fr.WriteHeaders(HeadersFrameParam{
3160 StreamID: hf.StreamID,
3163 BlockFragment: buf.Bytes(),
3166 errs <- fmt.Errorf("server2 failed writing response HEADERS: %v", err)
3172 for k := 0; k < 3; k++ {
3178 case <-time.After(1 * time.Second):
3179 t.Errorf("timed out")
3185 case c := <-connToClose:
3193 func TestTransportRetryAfterRefusedStream(t *testing.T) {
3194 clientDone := make(chan struct{})
3195 ct := newClientTester(t)
3196 ct.client = func() error {
3197 defer ct.cc.(*net.TCPConn).CloseWrite()
3198 defer close(clientDone)
3199 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
3200 resp, err := ct.tr.RoundTrip(req)
3202 return fmt.Errorf("RoundTrip: %v", err)
3205 if resp.StatusCode != 204 {
3206 return fmt.Errorf("Status = %v; want 204", resp.StatusCode)
3210 ct.server = func() error {
3212 var buf bytes.Buffer
3213 enc := hpack.NewEncoder(&buf)
3217 f, err := ct.fr.ReadFrame()
3221 // If the client's done, it
3222 // will have reported any
3223 // errors on its side.
3229 switch f := f.(type) {
3230 case *WindowUpdateFrame, *SettingsFrame:
3232 if !f.HeadersEnded() {
3233 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
3237 ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream)
3239 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"})
3240 ct.fr.WriteHeaders(HeadersFrameParam{
3241 StreamID: f.StreamID,
3244 BlockFragment: buf.Bytes(),
3248 return fmt.Errorf("Unexpected client frame %v", f)
3255 func TestTransportRetryHasLimit(t *testing.T) {
3256 // Skip in short mode because the total expected delay is 1s+2s+4s+8s+16s=29s.
3257 if testing.Short() {
3258 t.Skip("skipping long test in short mode")
3260 clientDone := make(chan struct{})
3261 ct := newClientTester(t)
3262 ct.client = func() error {
3263 defer ct.cc.(*net.TCPConn).CloseWrite()
3264 defer close(clientDone)
3265 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
3266 resp, err := ct.tr.RoundTrip(req)
3268 return fmt.Errorf("RoundTrip expected error, got response: %+v", resp)
3270 t.Logf("expected error, got: %v", err)
3273 ct.server = func() error {
3276 f, err := ct.fr.ReadFrame()
3280 // If the client's done, it
3281 // will have reported any
3282 // errors on its side.
3288 switch f := f.(type) {
3289 case *WindowUpdateFrame, *SettingsFrame:
3291 if !f.HeadersEnded() {
3292 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
3294 ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream)
3296 return fmt.Errorf("Unexpected client frame %v", f)
3303 func TestTransportResponseDataBeforeHeaders(t *testing.T) {
3304 ct := newClientTester(t)
3305 ct.client = func() error {
3306 defer ct.cc.(*net.TCPConn).CloseWrite()
3307 req := httptest.NewRequest("GET", "https://dummy.tld/", nil)
3308 // First request is normal to ensure the check is per stream and not per connection.
3309 _, err := ct.tr.RoundTrip(req)
3311 return fmt.Errorf("RoundTrip expected no error, got: %v", err)
3313 // Second request returns a DATA frame with no HEADERS.
3314 resp, err := ct.tr.RoundTrip(req)
3316 return fmt.Errorf("RoundTrip expected error, got response: %+v", resp)
3318 if err, ok := err.(StreamError); !ok || err.Code != ErrCodeProtocol {
3319 return fmt.Errorf("expected stream PROTOCOL_ERROR, got: %v", err)
3323 ct.server = func() error {
3326 f, err := ct.fr.ReadFrame()
3329 } else if err != nil {
3332 switch f := f.(type) {
3333 case *WindowUpdateFrame, *SettingsFrame:
3337 // Send a valid response to first request.
3338 var buf bytes.Buffer
3339 enc := hpack.NewEncoder(&buf)
3340 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
3341 ct.fr.WriteHeaders(HeadersFrameParam{
3342 StreamID: f.StreamID,
3345 BlockFragment: buf.Bytes(),
3348 ct.fr.WriteData(f.StreamID, true, []byte("payload"))
3351 return fmt.Errorf("Unexpected client frame %v", f)
3357 func TestTransportRequestsStallAtServerLimit(t *testing.T) {
3358 const maxConcurrent = 2
3360 greet := make(chan struct{}) // server sends initial SETTINGS frame
3361 gotRequest := make(chan struct{}) // server received a request
3362 clientDone := make(chan struct{})
3364 // Collect errors from goroutines.
3365 var wg sync.WaitGroup
3366 errs := make(chan error, 100)
3370 for err := range errs {
3375 // We will send maxConcurrent+2 requests. This checker goroutine waits for the
3376 // following stages:
3377 // 1. The first maxConcurrent requests are received by the server.
3378 // 2. The client will cancel the next request
3379 // 3. The server is unblocked so it can service the first maxConcurrent requests
3380 // 4. The client will send the final request
3382 unblockClient := make(chan struct{})
3383 clientRequestCancelled := make(chan struct{})
3384 unblockServer := make(chan struct{})
3388 for k := 0; k < maxConcurrent; k++ {
3392 close(unblockClient)
3393 <-clientRequestCancelled
3394 // Stage 3: give some time for the final RoundTrip call to be scheduled and
3395 // verify that the final request is not sent.
3396 time.Sleep(50 * time.Millisecond)
3399 errs <- errors.New("last request did not stall")
3400 close(unblockServer)
3404 close(unblockServer)
3409 ct := newClientTester(t)
3410 ct.client = func() error {
3411 var wg sync.WaitGroup
3415 ct.cc.(*net.TCPConn).CloseWrite()
3417 for k := 0; k < maxConcurrent+2; k++ {
3421 // Don't send the second request until after receiving SETTINGS from the server
3422 // to avoid a race where we use the default SettingMaxConcurrentStreams, which
3423 // is much larger than maxConcurrent. We have to send the first request before
3424 // waiting because the first request triggers the dial and greet.
3428 // Block until maxConcurrent requests are sent before sending any more.
3429 if k >= maxConcurrent {
3432 req, _ := http.NewRequest("GET", fmt.Sprintf("https://dummy.tld/%d", k), nil)
3433 if k == maxConcurrent {
3434 // This request will be canceled.
3435 cancel := make(chan struct{})
3438 _, err := ct.tr.RoundTrip(req)
3439 close(clientRequestCancelled)
3441 errs <- fmt.Errorf("RoundTrip(%d) should have failed due to cancel", k)
3445 resp, err := ct.tr.RoundTrip(req)
3447 errs <- fmt.Errorf("RoundTrip(%d): %v", k, err)
3450 ioutil.ReadAll(resp.Body)
3452 if resp.StatusCode != 204 {
3453 errs <- fmt.Errorf("Status = %v; want 204", resp.StatusCode)
3462 ct.server = func() error {
3463 var wg sync.WaitGroup
3466 ct.greet(Setting{SettingMaxConcurrentStreams, maxConcurrent})
3468 // Server write loop.
3469 var buf bytes.Buffer
3470 enc := hpack.NewEncoder(&buf)
3471 writeResp := make(chan uint32, maxConcurrent+1)
3477 for id := range writeResp {
3479 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"})
3480 ct.fr.WriteHeaders(HeadersFrameParam{
3484 BlockFragment: buf.Bytes(),
3489 // Server read loop.
3492 f, err := ct.fr.ReadFrame()
3496 // If the client's done, it will have reported any errors on its side.
3502 switch f := f.(type) {
3503 case *WindowUpdateFrame:
3504 case *SettingsFrame:
3505 // Wait for the client SETTINGS ack until ending the greet.
3508 if !f.HeadersEnded() {
3509 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
3511 gotRequest <- struct{}{}
3513 writeResp <- f.StreamID
3514 if nreq == maxConcurrent+1 {
3518 return fmt.Errorf("Unexpected client frame %v", f)
3526 func TestAuthorityAddr(t *testing.T) {
3528 scheme, authority string
3531 {"http", "foo.com", "foo.com:80"},
3532 {"https", "foo.com", "foo.com:443"},
3533 {"https", "foo.com:1234", "foo.com:1234"},
3534 {"https", "1.2.3.4:1234", "1.2.3.4:1234"},
3535 {"https", "1.2.3.4", "1.2.3.4:443"},
3536 {"https", "[::1]:1234", "[::1]:1234"},
3537 {"https", "[::1]", "[::1]:443"},
3539 for _, tt := range tests {
3540 got := authorityAddr(tt.scheme, tt.authority)
3542 t.Errorf("authorityAddr(%q, %q) = %q; want %q", tt.scheme, tt.authority, got, tt.want)
3547 // Issue 20448: stop allocating for DATA frames' payload after
3548 // Response.Body.Close is called.
3549 func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) {
3550 megabyteZero := make([]byte, 1<<20)
3552 writeErr := make(chan error, 1)
3554 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
3555 w.(http.Flusher).Flush()
3557 for i := 0; i < 100; i++ {
3558 n, err := w.Write(megabyteZero)
3565 t.Logf("wrote all %d bytes", sum)
3570 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
3571 defer tr.CloseIdleConnections()
3572 c := &http.Client{Transport: tr}
3573 res, err := c.Get(st.ts.URL)
3578 if _, err := res.Body.Read(buf[:]); err != nil {
3581 if err := res.Body.Close(); err != nil {
3585 trb, ok := res.Body.(transportResponseBody)
3587 t.Fatalf("res.Body = %T; want transportResponseBody", res.Body)
3589 if trb.cs.bufPipe.b != nil {
3590 t.Errorf("response body pipe is still open")
3593 gotErr := <-writeErr
3595 t.Errorf("Handler unexpectedly managed to write its entire response without getting an error")
3596 } else if gotErr != errStreamClosed {
3597 t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr)
3601 // Issue 18891: make sure Request.Body == NoBody means no DATA frame
3602 // is ever sent, even if empty.
3603 func TestTransportNoBodyMeansNoDATA(t *testing.T) {
3604 ct := newClientTester(t)
3606 unblockClient := make(chan bool)
3608 ct.client = func() error {
3609 req, _ := http.NewRequest("GET", "https://dummy.tld/", go18httpNoBody())
3610 ct.tr.RoundTrip(req)
3614 ct.server = func() error {
3615 defer close(unblockClient)
3616 defer ct.cc.(*net.TCPConn).Close()
3620 f, err := ct.fr.ReadFrame()
3622 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
3624 switch f := f.(type) {
3626 return fmt.Errorf("Got %T; want HeadersFrame", f)
3627 case *WindowUpdateFrame, *SettingsFrame:
3630 if !f.StreamEnded() {
3631 return fmt.Errorf("got headers frame without END_STREAM")
3640 func benchSimpleRoundTrip(b *testing.B, nHeaders int) {
3641 defer disableGoroutineTracking()()
3643 st := newServerTester(b,
3644 func(w http.ResponseWriter, r *http.Request) {
3651 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
3652 defer tr.CloseIdleConnections()
3654 req, err := http.NewRequest("GET", st.ts.URL, nil)
3659 for i := 0; i < nHeaders; i++ {
3660 name := fmt.Sprint("A-", i)
3661 req.Header.Set(name, "*")
3666 for i := 0; i < b.N; i++ {
3667 res, err := tr.RoundTrip(req)
3672 b.Fatalf("RoundTrip err = %v; want nil", err)
3675 if res.StatusCode != http.StatusOK {
3676 b.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK)
3681 func BenchmarkClientRequestHeaders(b *testing.B) {
3682 b.Run(" 0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0) })
3683 b.Run(" 10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 10) })
3684 b.Run(" 100 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 100) })
3685 b.Run("1000 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 1000) })