blob: 4f3b8a135bf4419940a9aacad51f5efd37277123 [file] [log] [blame]
Andrew Gerrand6d10a0c2015-10-14 04:11:41 +00001// 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.
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +00004
5package http2
6
7import (
Brad Fitzpatrick438097d2015-12-01 22:16:42 +00008 "bufio"
9 "bytes"
Blake Mizeranye1a58162015-10-24 16:42:11 -070010 "crypto/tls"
Brad Fitzpatrick438097d2015-12-01 22:16:42 +000011 "errors"
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000012 "flag"
Brad Fitzpatrick2fd7f152015-10-29 17:44:04 +000013 "fmt"
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -080014 "io"
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -080015 "io/ioutil"
Brad Fitzpatrick2fd7f152015-10-29 17:44:04 +000016 "math/rand"
Blake Mizeranye1a58162015-10-24 16:42:11 -070017 "net"
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000018 "net/http"
Blake Mizeranyce84af22015-10-27 23:17:12 -070019 "net/url"
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000020 "os"
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -080021 "reflect"
Brad Fitzpatrick4d07e8a2016-05-20 18:55:47 +000022 "runtime"
Brad Fitzpatrick493a2622016-02-04 19:41:12 +000023 "sort"
Brad Fitzpatrick438097d2015-12-01 22:16:42 +000024 "strconv"
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -080025 "strings"
Blake Mizeranye1a58162015-10-24 16:42:11 -070026 "sync"
Brad Fitzpatrick438097d2015-12-01 22:16:42 +000027 "sync/atomic"
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000028 "testing"
Blake Mizerany35769072015-02-08 22:09:17 -080029 "time"
Brad Fitzpatrick438097d2015-12-01 22:16:42 +000030
31 "golang.org/x/net/http2/hpack"
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000032)
33
Brad Fitzpatrick07ee6802015-02-03 12:57:45 +000034var (
35 extNet = flag.Bool("extnet", false, "do external network tests")
36 transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport")
Blake Mizerany1b277612015-10-27 22:40:40 -070037 insecure = flag.Bool("insecure", false, "insecure TLS dials") // TODO: dead code. remove?
Brad Fitzpatrick07ee6802015-02-03 12:57:45 +000038)
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000039
Blake Mizeranye1a58162015-10-24 16:42:11 -070040var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true}
41
Brad Fitzpatrickd3b63542015-02-08 17:02:49 -080042func TestTransportExternal(t *testing.T) {
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000043 if !*extNet {
44 t.Skip("skipping external network test")
45 }
Brad Fitzpatrick07ee6802015-02-03 12:57:45 +000046 req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil)
Blake Mizeranye1a58162015-10-24 16:42:11 -070047 rt := &Transport{TLSClientConfig: tlsConfigInsecure}
Brad Fitzpatrickfcb18db2015-02-02 15:41:30 +000048 res, err := rt.RoundTrip(req)
49 if err != nil {
50 t.Fatalf("%v", err)
51 }
52 res.Write(os.Stdout)
53}
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -080054
ayanamistb3e9c8f2016-05-18 06:54:12 +080055func startH2cServer(t *testing.T) net.Listener {
56 h2Server := &Server{}
57 l := newLocalListener(t)
58 go func() {
59 conn, err := l.Accept()
60 if err != nil {
61 t.Error(err)
62 return
63 }
64 h2Server.ServeConn(conn, &ServeConnOpts{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
65 fmt.Fprintf(w, "Hello, %v", r.URL.Path)
66 })})
67 }()
68 return l
69}
70
71func TestTransportH2c(t *testing.T) {
72 l := startH2cServer(t)
73 defer l.Close()
74 req, err := http.NewRequest("GET", "http://"+l.Addr().String()+"/foobar", nil)
75 if err != nil {
76 t.Fatal(err)
77 }
78 tr := &Transport{
79 AllowHTTP: true,
80 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
81 return net.Dial(network, addr)
82 },
83 }
84 res, err := tr.RoundTrip(req)
85 if err != nil {
86 t.Fatal(err)
87 }
88 if res.ProtoMajor != 2 {
89 t.Fatal("proto not h2c")
90 }
91 body, err := ioutil.ReadAll(res.Body)
92 if err != nil {
93 t.Fatal(err)
94 }
95 if got, want := string(body), "Hello, /foobar"; got != want {
96 t.Fatalf("response got %v, want %v", got, want)
97 }
98}
99
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800100func TestTransport(t *testing.T) {
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -0800101 const body = "sup"
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800102 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -0800103 io.WriteString(w, body)
Brad Fitzpatrickcd8c2702015-10-15 20:01:14 +0000104 }, optOnlyServer)
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800105 defer st.Close()
106
Blake Mizeranye1a58162015-10-24 16:42:11 -0700107 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -0800108 defer tr.CloseIdleConnections()
109
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -0800110 req, err := http.NewRequest("GET", st.ts.URL, nil)
111 if err != nil {
112 t.Fatal(err)
113 }
114 res, err := tr.RoundTrip(req)
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800115 if err != nil {
116 t.Fatal(err)
117 }
118 defer res.Body.Close()
119
120 t.Logf("Got res: %+v", res)
121 if g, w := res.StatusCode, 200; g != w {
122 t.Errorf("StatusCode = %v; want %v", g, w)
123 }
124 if g, w := res.Status, "200 OK"; g != w {
125 t.Errorf("Status = %q; want %q", g, w)
126 }
127 wantHeader := http.Header{
128 "Content-Length": []string{"3"},
129 "Content-Type": []string{"text/plain; charset=utf-8"},
Brad Fitzpatrickc745c362015-11-24 17:14:16 -0800130 "Date": []string{"XXX"}, // see cleanDate
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800131 }
Brad Fitzpatrickc745c362015-11-24 17:14:16 -0800132 cleanDate(res)
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800133 if !reflect.DeepEqual(res.Header, wantHeader) {
134 t.Errorf("res Header = %v; want %v", res.Header, wantHeader)
135 }
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -0800136 if res.Request != req {
137 t.Errorf("Response.Request = %p; want %p", res.Request, req)
138 }
139 if res.TLS == nil {
Matt Layher6c53fec2015-05-03 16:39:16 -0400140 t.Error("Response.TLS = nil; want non-nil")
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -0800141 }
142 slurp, err := ioutil.ReadAll(res.Body)
143 if err != nil {
Matt Layher6c53fec2015-05-03 16:39:16 -0400144 t.Errorf("Body read: %v", err)
Brad Fitzpatrickb4eaf1c2015-02-08 17:52:35 -0800145 } else if string(slurp) != body {
146 t.Errorf("Body = %q; want %q", slurp, body)
147 }
Brad Fitzpatrickebe9b942015-02-08 17:23:16 -0800148}
Brad Fitzpatrick4d07e8a2016-05-20 18:55:47 +0000149
Brad Fitzpatrick493a2622016-02-04 19:41:12 +0000150func onSameConn(t *testing.T, modReq func(*http.Request)) bool {
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -0800151 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
152 io.WriteString(w, r.RemoteAddr)
Brad Fitzpatricka7282882016-07-07 15:24:52 -0700153 }, optOnlyServer, func(c net.Conn, st http.ConnState) {
154 t.Logf("conn %v is now state %v", c.RemoteAddr(), st)
155 })
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -0800156 defer st.Close()
Blake Mizeranye1a58162015-10-24 16:42:11 -0700157 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -0800158 defer tr.CloseIdleConnections()
159 get := func() string {
160 req, err := http.NewRequest("GET", st.ts.URL, nil)
161 if err != nil {
162 t.Fatal(err)
163 }
Brad Fitzpatrick493a2622016-02-04 19:41:12 +0000164 modReq(req)
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -0800165 res, err := tr.RoundTrip(req)
166 if err != nil {
167 t.Fatal(err)
168 }
169 defer res.Body.Close()
170 slurp, err := ioutil.ReadAll(res.Body)
171 if err != nil {
172 t.Fatalf("Body read: %v", err)
173 }
174 addr := strings.TrimSpace(string(slurp))
175 if addr == "" {
176 t.Fatalf("didn't get an addr in response")
177 }
178 return addr
179 }
180 first := get()
181 second := get()
Brad Fitzpatrick493a2622016-02-04 19:41:12 +0000182 return first == second
183}
184
185func TestTransportReusesConns(t *testing.T) {
186 if !onSameConn(t, func(*http.Request) {}) {
187 t.Errorf("first and second responses were on different connections")
188 }
189}
190
191func TestTransportReusesConn_RequestClose(t *testing.T) {
192 if onSameConn(t, func(r *http.Request) { r.Close = true }) {
193 t.Errorf("first and second responses were not on different connections")
194 }
195}
196
197func TestTransportReusesConn_ConnClose(t *testing.T) {
198 if onSameConn(t, func(r *http.Request) { r.Header.Set("Connection", "close") }) {
199 t.Errorf("first and second responses were not on different connections")
Brad Fitzpatrick45702ea2015-02-08 21:57:59 -0800200 }
201}
Blake Mizerany35769072015-02-08 22:09:17 -0800202
Brad Fitzpatrick195180c2015-11-30 18:41:58 +0000203// Tests that the Transport only keeps one pending dial open per destination address.
204// https://golang.org/issue/13397
205func TestTransportGroupsPendingDials(t *testing.T) {
206 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
207 io.WriteString(w, r.RemoteAddr)
208 }, optOnlyServer)
209 defer st.Close()
210 tr := &Transport{
211 TLSClientConfig: tlsConfigInsecure,
212 }
213 defer tr.CloseIdleConnections()
214 var (
215 mu sync.Mutex
216 dials = map[string]int{}
217 )
218 var wg sync.WaitGroup
219 for i := 0; i < 10; i++ {
220 wg.Add(1)
221 go func() {
222 defer wg.Done()
223 req, err := http.NewRequest("GET", st.ts.URL, nil)
224 if err != nil {
225 t.Error(err)
226 return
227 }
228 res, err := tr.RoundTrip(req)
229 if err != nil {
230 t.Error(err)
231 return
232 }
233 defer res.Body.Close()
234 slurp, err := ioutil.ReadAll(res.Body)
235 if err != nil {
236 t.Errorf("Body read: %v", err)
237 }
238 addr := strings.TrimSpace(string(slurp))
239 if addr == "" {
240 t.Errorf("didn't get an addr in response")
241 }
242 mu.Lock()
243 dials[addr]++
244 mu.Unlock()
245 }()
246 }
247 wg.Wait()
248 if len(dials) != 1 {
249 t.Errorf("saw %d dials; want 1: %v", len(dials), dials)
250 }
251 tr.CloseIdleConnections()
252 if err := retry(50, 10*time.Millisecond, func() error {
253 cp, ok := tr.connPool().(*clientConnPool)
254 if !ok {
255 return fmt.Errorf("Conn pool is %T; want *clientConnPool", tr.connPool())
256 }
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000257 cp.mu.Lock()
258 defer cp.mu.Unlock()
Brad Fitzpatrick195180c2015-11-30 18:41:58 +0000259 if len(cp.dialing) != 0 {
260 return fmt.Errorf("dialing map = %v; want empty", cp.dialing)
261 }
262 if len(cp.conns) != 0 {
263 return fmt.Errorf("conns = %v; want empty", cp.conns)
264 }
265 if len(cp.keys) != 0 {
266 return fmt.Errorf("keys = %v; want empty", cp.keys)
267 }
268 return nil
269 }); err != nil {
Mikio Hara1d7a0b22016-01-07 09:41:45 +0900270 t.Errorf("State of pool after CloseIdleConnections: %v", err)
Brad Fitzpatrick195180c2015-11-30 18:41:58 +0000271 }
272}
273
274func retry(tries int, delay time.Duration, fn func() error) error {
275 var err error
276 for i := 0; i < tries; i++ {
277 err = fn()
278 if err == nil {
279 return nil
280 }
281 time.Sleep(delay)
282 }
283 return err
284}
285
Blake Mizerany35769072015-02-08 22:09:17 -0800286func TestTransportAbortClosesPipes(t *testing.T) {
287 shutdown := make(chan struct{})
288 st := newServerTester(t,
289 func(w http.ResponseWriter, r *http.Request) {
290 w.(http.Flusher).Flush()
291 <-shutdown
292 },
293 optOnlyServer,
294 )
295 defer st.Close()
296 defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
297
298 done := make(chan struct{})
299 requestMade := make(chan struct{})
300 go func() {
301 defer close(done)
Blake Mizeranye1a58162015-10-24 16:42:11 -0700302 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
Blake Mizerany35769072015-02-08 22:09:17 -0800303 req, err := http.NewRequest("GET", st.ts.URL, nil)
304 if err != nil {
305 t.Fatal(err)
306 }
307 res, err := tr.RoundTrip(req)
308 if err != nil {
309 t.Fatal(err)
310 }
311 defer res.Body.Close()
312 close(requestMade)
313 _, err = ioutil.ReadAll(res.Body)
314 if err == nil {
315 t.Error("expected error from res.Body.Read")
316 }
317 }()
318
319 <-requestMade
320 // Now force the serve loop to end, via closing the connection.
321 st.closeConn()
322 // deadlock? that's a bug.
323 select {
324 case <-done:
325 case <-time.After(3 * time.Second):
326 t.Fatal("timeout")
327 }
328}
Brad Fitzpatrick09d2a412015-10-21 15:37:53 -0500329
Blake Mizeranyce84af22015-10-27 23:17:12 -0700330// TODO: merge this with TestTransportBody to make TestTransportRequest? This
331// could be a table-driven test with extra goodies.
332func TestTransportPath(t *testing.T) {
333 gotc := make(chan *url.URL, 1)
334 st := newServerTester(t,
335 func(w http.ResponseWriter, r *http.Request) {
336 gotc <- r.URL
337 },
338 optOnlyServer,
339 )
340 defer st.Close()
341
342 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
343 defer tr.CloseIdleConnections()
344 const (
345 path = "/testpath"
346 query = "q=1"
347 )
348 surl := st.ts.URL + path + "?" + query
349 req, err := http.NewRequest("POST", surl, nil)
350 if err != nil {
351 t.Fatal(err)
352 }
353 c := &http.Client{Transport: tr}
354 res, err := c.Do(req)
355 if err != nil {
356 t.Fatal(err)
357 }
358 defer res.Body.Close()
359 got := <-gotc
360 if got.Path != path {
361 t.Errorf("Read Path = %q; want %q", got.Path, path)
362 }
363 if got.RawQuery != query {
364 t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query)
365 }
366}
367
Brad Fitzpatrick2fd7f152015-10-29 17:44:04 +0000368func randString(n int) string {
369 rnd := rand.New(rand.NewSource(int64(n)))
370 b := make([]byte, n)
371 for i := range b {
372 b[i] = byte(rnd.Intn(256))
373 }
374 return string(b)
375}
376
Brad Fitzpatrick09d2a412015-10-21 15:37:53 -0500377func TestTransportBody(t *testing.T) {
Brad Fitzpatrick4d06dbd2016-03-21 23:17:53 +0000378 bodyTests := []struct {
379 body string
380 noContentLen bool
381 }{
382 {body: "some message"},
383 {body: "some message", noContentLen: true},
384 {body: ""},
385 {body: "", noContentLen: true},
386 {body: strings.Repeat("a", 1<<20), noContentLen: true},
387 {body: strings.Repeat("a", 1<<20)},
388 {body: randString(16<<10 - 1)},
389 {body: randString(16 << 10)},
390 {body: randString(16<<10 + 1)},
391 {body: randString(512<<10 - 1)},
392 {body: randString(512 << 10)},
393 {body: randString(512<<10 + 1)},
394 {body: randString(1<<20 - 1)},
395 {body: randString(1 << 20)},
396 {body: randString(1<<20 + 2)},
397 }
398
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800399 type reqInfo struct {
400 req *http.Request
401 slurp []byte
402 err error
403 }
404 gotc := make(chan reqInfo, 1)
Brad Fitzpatrick09d2a412015-10-21 15:37:53 -0500405 st := newServerTester(t,
406 func(w http.ResponseWriter, r *http.Request) {
407 slurp, err := ioutil.ReadAll(r.Body)
408 if err != nil {
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800409 gotc <- reqInfo{err: err}
Brad Fitzpatrick09d2a412015-10-21 15:37:53 -0500410 } else {
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800411 gotc <- reqInfo{req: r, slurp: slurp}
Brad Fitzpatrick09d2a412015-10-21 15:37:53 -0500412 }
413 },
414 optOnlyServer,
415 )
416 defer st.Close()
417
Blake Mizerany1b277612015-10-27 22:40:40 -0700418 for i, tt := range bodyTests {
419 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
420 defer tr.CloseIdleConnections()
421
422 var body io.Reader = strings.NewReader(tt.body)
423 if tt.noContentLen {
424 body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods
425 }
426 req, err := http.NewRequest("POST", st.ts.URL, body)
427 if err != nil {
428 t.Fatalf("#%d: %v", i, err)
429 }
430 c := &http.Client{Transport: tr}
431 res, err := c.Do(req)
432 if err != nil {
433 t.Fatalf("#%d: %v", i, err)
434 }
435 defer res.Body.Close()
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800436 ri := <-gotc
437 if ri.err != nil {
Mikio Hara7f882712016-02-05 10:48:01 +0900438 t.Errorf("#%d: read error: %v", i, ri.err)
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800439 continue
440 }
441 if got := string(ri.slurp); got != tt.body {
Brad Fitzpatrick2fd7f152015-10-29 17:44:04 +0000442 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))
Blake Mizerany1b277612015-10-27 22:40:40 -0700443 }
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800444 wantLen := int64(len(tt.body))
445 if tt.noContentLen && tt.body != "" {
446 wantLen = -1
447 }
448 if ri.req.ContentLength != wantLen {
449 t.Errorf("#%d. handler got ContentLength = %v; want %v", i, ri.req.ContentLength, wantLen)
450 }
Brad Fitzpatrick09d2a412015-10-21 15:37:53 -0500451 }
452}
Blake Mizeranye1a58162015-10-24 16:42:11 -0700453
Brad Fitzpatrick2fd7f152015-10-29 17:44:04 +0000454func shortString(v string) string {
455 const maxLen = 100
456 if len(v) <= maxLen {
457 return v
458 }
459 return fmt.Sprintf("%v[...%d bytes omitted...]%v", v[:maxLen/2], len(v)-maxLen, v[len(v)-maxLen/2:])
460}
461
Blake Mizeranye1a58162015-10-24 16:42:11 -0700462func TestTransportDialTLS(t *testing.T) {
463 var mu sync.Mutex // guards following
464 var gotReq, didDial bool
465
466 ts := newServerTester(t,
467 func(w http.ResponseWriter, r *http.Request) {
468 mu.Lock()
469 gotReq = true
470 mu.Unlock()
471 },
472 optOnlyServer,
473 )
474 defer ts.Close()
475 tr := &Transport{
476 DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
477 mu.Lock()
478 didDial = true
479 mu.Unlock()
480 cfg.InsecureSkipVerify = true
481 c, err := tls.Dial(netw, addr, cfg)
482 if err != nil {
483 return nil, err
484 }
485 return c, c.Handshake()
486 },
487 }
488 defer tr.CloseIdleConnections()
489 client := &http.Client{Transport: tr}
490 res, err := client.Get(ts.ts.URL)
491 if err != nil {
492 t.Fatal(err)
493 }
494 res.Body.Close()
495 mu.Lock()
496 if !gotReq {
497 t.Error("didn't get request")
498 }
499 if !didDial {
500 t.Error("didn't use dial hook")
501 }
502}
Brad Fitzpatrick042ba422015-11-08 11:16:06 +0100503
504func TestConfigureTransport(t *testing.T) {
505 t1 := &http.Transport{}
506 err := ConfigureTransport(t1)
507 if err == errTransportVersion {
508 t.Skip(err)
509 }
510 if err != nil {
511 t.Fatal(err)
512 }
513 if got := fmt.Sprintf("%#v", *t1); !strings.Contains(got, `"h2"`) {
514 // Laziness, to avoid buildtags.
515 t.Errorf("stringification of HTTP/1 transport didn't contain \"h2\": %v", got)
516 }
Brad Fitzpatrickb304fd02015-12-14 17:57:33 +0000517 wantNextProtos := []string{"h2", "http/1.1"}
Brad Fitzpatrick042ba422015-11-08 11:16:06 +0100518 if t1.TLSClientConfig == nil {
519 t.Errorf("nil t1.TLSClientConfig")
Brad Fitzpatrickb304fd02015-12-14 17:57:33 +0000520 } else if !reflect.DeepEqual(t1.TLSClientConfig.NextProtos, wantNextProtos) {
521 t.Errorf("TLSClientConfig.NextProtos = %q; want %q", t1.TLSClientConfig.NextProtos, wantNextProtos)
Brad Fitzpatrick042ba422015-11-08 11:16:06 +0100522 }
523 if err := ConfigureTransport(t1); err == nil {
524 t.Error("unexpected success on second call to ConfigureTransport")
525 }
526
527 // And does it work?
528 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
529 io.WriteString(w, r.Proto)
530 }, optOnlyServer)
531 defer st.Close()
532
533 t1.TLSClientConfig.InsecureSkipVerify = true
534 c := &http.Client{Transport: t1}
535 res, err := c.Get(st.ts.URL)
536 if err != nil {
537 t.Fatal(err)
538 }
539 slurp, err := ioutil.ReadAll(res.Body)
540 if err != nil {
541 t.Fatal(err)
542 }
543 if got, want := string(slurp), "HTTP/2.0"; got != want {
544 t.Errorf("body = %q; want %q", got, want)
545 }
546}
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000547
548type capitalizeReader struct {
549 r io.Reader
550}
551
552func (cr capitalizeReader) Read(p []byte) (n int, err error) {
553 n, err = cr.r.Read(p)
554 for i, b := range p[:n] {
555 if b >= 'a' && b <= 'z' {
556 p[i] = b - ('a' - 'A')
557 }
558 }
559 return
560}
561
562type flushWriter struct {
563 w io.Writer
564}
565
566func (fw flushWriter) Write(p []byte) (n int, err error) {
567 n, err = fw.w.Write(p)
568 if f, ok := fw.w.(http.Flusher); ok {
569 f.Flush()
570 }
571 return
572}
573
574type clientTester struct {
575 t *testing.T
576 tr *Transport
577 sc, cc net.Conn // server and client conn
578 fr *Framer // server's framer
579 client func() error
580 server func() error
581}
582
583func newClientTester(t *testing.T) *clientTester {
584 var dialOnce struct {
585 sync.Mutex
586 dialed bool
587 }
588 ct := &clientTester{
589 t: t,
590 }
591 ct.tr = &Transport{
592 TLSClientConfig: tlsConfigInsecure,
593 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
594 dialOnce.Lock()
595 defer dialOnce.Unlock()
596 if dialOnce.dialed {
597 return nil, errors.New("only one dial allowed in test mode")
598 }
599 dialOnce.dialed = true
600 return ct.cc, nil
601 },
602 }
603
604 ln := newLocalListener(t)
605 cc, err := net.Dial("tcp", ln.Addr().String())
606 if err != nil {
607 t.Fatal(err)
608
609 }
610 sc, err := ln.Accept()
611 if err != nil {
612 t.Fatal(err)
613 }
614 ln.Close()
615 ct.cc = cc
616 ct.sc = sc
617 ct.fr = NewFramer(sc, sc)
618 return ct
619}
620
621func newLocalListener(t *testing.T) net.Listener {
622 ln, err := net.Listen("tcp4", "127.0.0.1:0")
623 if err == nil {
624 return ln
625 }
626 ln, err = net.Listen("tcp6", "[::1]:0")
627 if err != nil {
628 t.Fatal(err)
629 }
630 return ln
631}
632
633func (ct *clientTester) greet() {
634 buf := make([]byte, len(ClientPreface))
635 _, err := io.ReadFull(ct.sc, buf)
636 if err != nil {
637 ct.t.Fatalf("reading client preface: %v", err)
638 }
639 f, err := ct.fr.ReadFrame()
640 if err != nil {
641 ct.t.Fatalf("Reading client settings frame: %v", err)
642 }
643 if sf, ok := f.(*SettingsFrame); !ok {
644 ct.t.Fatalf("Wanted client settings frame; got %v", f)
645 _ = sf // stash it away?
646 }
647 if err := ct.fr.WriteSettings(); err != nil {
648 ct.t.Fatal(err)
649 }
650 if err := ct.fr.WriteSettingsAck(); err != nil {
651 ct.t.Fatal(err)
652 }
653}
654
Brad Fitzpatrick520af5d2016-01-07 02:53:08 +0000655func (ct *clientTester) cleanup() {
656 ct.tr.CloseIdleConnections()
657}
658
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000659func (ct *clientTester) run() {
660 errc := make(chan error, 2)
661 ct.start("client", errc, ct.client)
662 ct.start("server", errc, ct.server)
Brad Fitzpatrick520af5d2016-01-07 02:53:08 +0000663 defer ct.cleanup()
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000664 for i := 0; i < 2; i++ {
665 if err := <-errc; err != nil {
666 ct.t.Error(err)
667 return
668 }
669 }
670}
671
672func (ct *clientTester) start(which string, errc chan<- error, fn func() error) {
673 go func() {
674 finished := false
675 var err error
676 defer func() {
677 if !finished {
678 err = fmt.Errorf("%s goroutine didn't finish.", which)
679 } else if err != nil {
680 err = fmt.Errorf("%s: %v", which, err)
681 }
682 errc <- err
683 }()
684 err = fn()
685 finished = true
686 }()
687}
688
689type countingReader struct {
690 n *int64
691}
692
693func (r countingReader) Read(p []byte) (n int, err error) {
694 for i := range p {
695 p[i] = byte(i)
696 }
697 atomic.AddInt64(r.n, int64(len(p)))
698 return len(p), err
699}
700
701func TestTransportReqBodyAfterResponse_200(t *testing.T) { testTransportReqBodyAfterResponse(t, 200) }
702func TestTransportReqBodyAfterResponse_403(t *testing.T) { testTransportReqBodyAfterResponse(t, 403) }
703
704func testTransportReqBodyAfterResponse(t *testing.T, status int) {
705 const bodySize = 10 << 20
706 ct := newClientTester(t)
707 ct.client = func() error {
708 var n int64 // atomic
709 req, err := http.NewRequest("PUT", "https://dummy.tld/", io.LimitReader(countingReader{&n}, bodySize))
710 if err != nil {
711 return err
712 }
713 res, err := ct.tr.RoundTrip(req)
714 if err != nil {
715 return fmt.Errorf("RoundTrip: %v", err)
716 }
717 defer res.Body.Close()
718 if res.StatusCode != status {
719 return fmt.Errorf("status code = %v; want %v", res.StatusCode, status)
720 }
721 slurp, err := ioutil.ReadAll(res.Body)
722 if err != nil {
723 return fmt.Errorf("Slurp: %v", err)
724 }
725 if len(slurp) > 0 {
726 return fmt.Errorf("unexpected body: %q", slurp)
727 }
728 if status == 200 {
729 if got := atomic.LoadInt64(&n); got != bodySize {
730 return fmt.Errorf("For 200 response, Transport wrote %d bytes; want %d", got, bodySize)
731 }
732 } else {
733 if got := atomic.LoadInt64(&n); got == 0 || got >= bodySize {
734 return fmt.Errorf("For %d response, Transport wrote %d bytes; want (0,%d) exclusive", status, got, bodySize)
735 }
736 }
737 return nil
738 }
739 ct.server = func() error {
740 ct.greet()
741 var buf bytes.Buffer
742 enc := hpack.NewEncoder(&buf)
743 var dataRecv int64
744 var closed bool
745 for {
746 f, err := ct.fr.ReadFrame()
747 if err != nil {
748 return err
749 }
750 //println(fmt.Sprintf("server got frame: %v", f))
751 switch f := f.(type) {
752 case *WindowUpdateFrame, *SettingsFrame:
753 case *HeadersFrame:
754 if !f.HeadersEnded() {
755 return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
756 }
757 if f.StreamEnded() {
758 return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f)
759 }
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000760 case *DataFrame:
761 dataLen := len(f.Data())
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000762 if dataLen > 0 {
Brad Fitzpatrickc9a3c542016-07-13 11:36:29 -0600763 if dataRecv == 0 {
764 enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)})
765 ct.fr.WriteHeaders(HeadersFrameParam{
766 StreamID: f.StreamID,
767 EndHeaders: true,
768 EndStream: false,
769 BlockFragment: buf.Bytes(),
770 })
771 }
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000772 if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
773 return err
774 }
775 if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
776 return err
777 }
778 }
Brad Fitzpatrickc9a3c542016-07-13 11:36:29 -0600779 dataRecv += int64(dataLen)
780
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000781 if !closed && ((status != 200 && dataRecv > 0) ||
782 (status == 200 && dataRecv == bodySize)) {
783 closed = true
784 if err := ct.fr.WriteData(f.StreamID, true, nil); err != nil {
785 return err
786 }
787 return nil
788 }
789 default:
790 return fmt.Errorf("Unexpected client frame %v", f)
791 }
792 }
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000793 }
794 ct.run()
795}
796
797// See golang.org/issue/13444
798func TestTransportFullDuplex(t *testing.T) {
799 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
800 w.WriteHeader(200) // redundant but for clarity
801 w.(http.Flusher).Flush()
802 io.Copy(flushWriter{w}, capitalizeReader{r.Body})
803 fmt.Fprintf(w, "bye.\n")
804 }, optOnlyServer)
805 defer st.Close()
806
807 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
808 defer tr.CloseIdleConnections()
809 c := &http.Client{Transport: tr}
810
811 pr, pw := io.Pipe()
812 req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr))
813 if err != nil {
Mikio Haradfd9ed62016-05-26 10:07:17 +0900814 t.Fatal(err)
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000815 }
Brad Fitzpatrick5c0dae82016-01-18 14:52:20 -0800816 req.ContentLength = -1
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000817 res, err := c.Do(req)
818 if err != nil {
Mikio Haradfd9ed62016-05-26 10:07:17 +0900819 t.Fatal(err)
Brad Fitzpatrick438097d2015-12-01 22:16:42 +0000820 }
821 defer res.Body.Close()
822 if res.StatusCode != 200 {
823 t.Fatalf("StatusCode = %v; want %v", res.StatusCode, 200)
824 }
825 bs := bufio.NewScanner(res.Body)
826 want := func(v string) {
827 if !bs.Scan() {
828 t.Fatalf("wanted to read %q but Scan() = false, err = %v", v, bs.Err())
829 }
830 }
831 write := func(v string) {
832 _, err := io.WriteString(pw, v)
833 if err != nil {
834 t.Fatalf("pipe write: %v", err)
835 }
836 }
837 write("foo\n")
838 want("FOO")
839 write("bar\n")
840 want("BAR")
841 pw.Close()
842 want("bye.")
843 if err := bs.Err(); err != nil {
844 t.Fatal(err)
845 }
846}
Brad Fitzpatrick961116a2016-01-05 14:53:21 -0800847
848func TestTransportConnectRequest(t *testing.T) {
849 gotc := make(chan *http.Request, 1)
850 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
851 gotc <- r
852 }, optOnlyServer)
853 defer st.Close()
854
855 u, err := url.Parse(st.ts.URL)
856 if err != nil {
857 t.Fatal(err)
858 }
859
860 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
861 defer tr.CloseIdleConnections()
862 c := &http.Client{Transport: tr}
863
864 tests := []struct {
865 req *http.Request
866 want string
867 }{
868 {
869 req: &http.Request{
870 Method: "CONNECT",
871 Header: http.Header{},
872 URL: u,
873 },
874 want: u.Host,
875 },
876 {
877 req: &http.Request{
878 Method: "CONNECT",
879 Header: http.Header{},
880 URL: u,
881 Host: "example.com:123",
882 },
883 want: "example.com:123",
884 },
885 }
886
887 for i, tt := range tests {
888 res, err := c.Do(tt.req)
889 if err != nil {
890 t.Errorf("%d. RoundTrip = %v", i, err)
891 continue
892 }
893 res.Body.Close()
894 req := <-gotc
895 if req.Method != "CONNECT" {
896 t.Errorf("method = %q; want CONNECT", req.Method)
897 }
898 if req.Host != tt.want {
899 t.Errorf("Host = %q; want %q", req.Host, tt.want)
900 }
901 if req.URL.Host != tt.want {
902 t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want)
903 }
904 }
905}
Brad Fitzpatrick520af5d2016-01-07 02:53:08 +0000906
907type headerType int
908
909const (
910 noHeader headerType = iota // omitted
911 oneHeader
912 splitHeader // broken into continuation on purpose
913)
914
915const (
916 f0 = noHeader
917 f1 = oneHeader
918 f2 = splitHeader
919 d0 = false
920 d1 = true
921)
922
923// Test all 36 combinations of response frame orders:
924// (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) }
925// Generated by http://play.golang.org/p/SScqYKJYXd
926func TestTransportResPattern_c0h1d0t0(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f0) }
927func TestTransportResPattern_c0h1d0t1(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f1) }
928func TestTransportResPattern_c0h1d0t2(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f2) }
929func TestTransportResPattern_c0h1d1t0(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f0) }
930func TestTransportResPattern_c0h1d1t1(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f1) }
931func TestTransportResPattern_c0h1d1t2(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f2) }
932func TestTransportResPattern_c0h2d0t0(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f0) }
933func TestTransportResPattern_c0h2d0t1(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f1) }
934func TestTransportResPattern_c0h2d0t2(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f2) }
935func TestTransportResPattern_c0h2d1t0(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f0) }
936func TestTransportResPattern_c0h2d1t1(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f1) }
937func TestTransportResPattern_c0h2d1t2(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f2) }
938func TestTransportResPattern_c1h1d0t0(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f0) }
939func TestTransportResPattern_c1h1d0t1(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f1) }
940func TestTransportResPattern_c1h1d0t2(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f2) }
941func TestTransportResPattern_c1h1d1t0(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f0) }
942func TestTransportResPattern_c1h1d1t1(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f1) }
943func TestTransportResPattern_c1h1d1t2(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f2) }
944func TestTransportResPattern_c1h2d0t0(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f0) }
945func TestTransportResPattern_c1h2d0t1(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f1) }
946func TestTransportResPattern_c1h2d0t2(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f2) }
947func TestTransportResPattern_c1h2d1t0(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f0) }
948func TestTransportResPattern_c1h2d1t1(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f1) }
949func TestTransportResPattern_c1h2d1t2(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f2) }
950func TestTransportResPattern_c2h1d0t0(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f0) }
951func TestTransportResPattern_c2h1d0t1(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f1) }
952func TestTransportResPattern_c2h1d0t2(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f2) }
953func TestTransportResPattern_c2h1d1t0(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f0) }
954func TestTransportResPattern_c2h1d1t1(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f1) }
955func TestTransportResPattern_c2h1d1t2(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f2) }
956func TestTransportResPattern_c2h2d0t0(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f0) }
957func TestTransportResPattern_c2h2d0t1(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f1) }
958func TestTransportResPattern_c2h2d0t2(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f2) }
959func TestTransportResPattern_c2h2d1t0(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f0) }
960func TestTransportResPattern_c2h2d1t1(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f1) }
961func TestTransportResPattern_c2h2d1t2(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f2) }
962
963func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerType, withData bool, trailers headerType) {
964 const reqBody = "some request body"
965 const resBody = "some response body"
966
967 if resHeader == noHeader {
968 // TODO: test 100-continue followed by immediate
969 // server stream reset, without headers in the middle?
970 panic("invalid combination")
971 }
972
973 ct := newClientTester(t)
974 ct.client = func() error {
975 req, _ := http.NewRequest("POST", "https://dummy.tld/", strings.NewReader(reqBody))
976 if expect100Continue != noHeader {
977 req.Header.Set("Expect", "100-continue")
978 }
979 res, err := ct.tr.RoundTrip(req)
980 if err != nil {
981 return fmt.Errorf("RoundTrip: %v", err)
982 }
983 defer res.Body.Close()
984 if res.StatusCode != 200 {
985 return fmt.Errorf("status code = %v; want 200", res.StatusCode)
986 }
987 slurp, err := ioutil.ReadAll(res.Body)
988 if err != nil {
989 return fmt.Errorf("Slurp: %v", err)
990 }
991 wantBody := resBody
992 if !withData {
993 wantBody = ""
994 }
995 if string(slurp) != wantBody {
996 return fmt.Errorf("body = %q; want %q", slurp, wantBody)
997 }
998 if trailers == noHeader {
999 if len(res.Trailer) > 0 {
1000 t.Errorf("Trailer = %v; want none", res.Trailer)
1001 }
1002 } else {
1003 want := http.Header{"Some-Trailer": {"some-value"}}
1004 if !reflect.DeepEqual(res.Trailer, want) {
1005 t.Errorf("Trailer = %v; want %v", res.Trailer, want)
1006 }
1007 }
1008 return nil
1009 }
1010 ct.server = func() error {
1011 ct.greet()
1012 var buf bytes.Buffer
1013 enc := hpack.NewEncoder(&buf)
1014
1015 for {
1016 f, err := ct.fr.ReadFrame()
1017 if err != nil {
1018 return err
1019 }
Brad Fitzpatricke90d6d02016-07-15 16:59:30 +00001020 endStream := false
1021 send := func(mode headerType) {
1022 hbf := buf.Bytes()
1023 switch mode {
1024 case oneHeader:
1025 ct.fr.WriteHeaders(HeadersFrameParam{
1026 StreamID: f.Header().StreamID,
1027 EndHeaders: true,
1028 EndStream: endStream,
1029 BlockFragment: hbf,
1030 })
1031 case splitHeader:
1032 if len(hbf) < 2 {
1033 panic("too small")
1034 }
1035 ct.fr.WriteHeaders(HeadersFrameParam{
1036 StreamID: f.Header().StreamID,
1037 EndHeaders: false,
1038 EndStream: endStream,
1039 BlockFragment: hbf[:1],
1040 })
1041 ct.fr.WriteContinuation(f.Header().StreamID, true, hbf[1:])
1042 default:
1043 panic("bogus mode")
1044 }
1045 }
Brad Fitzpatrick520af5d2016-01-07 02:53:08 +00001046 switch f := f.(type) {
1047 case *WindowUpdateFrame, *SettingsFrame:
1048 case *DataFrame:
Brad Fitzpatricke90d6d02016-07-15 16:59:30 +00001049 if !f.StreamEnded() {
1050 // No need to send flow control tokens. The test request body is tiny.
1051 continue
Brad Fitzpatrick520af5d2016-01-07 02:53:08 +00001052 }
1053 // Response headers (1+ frames; 1 or 2 in this test, but never 0)
1054 {
1055 buf.Reset()
1056 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1057 enc.WriteField(hpack.HeaderField{Name: "x-foo", Value: "blah"})
1058 enc.WriteField(hpack.HeaderField{Name: "x-bar", Value: "more"})
1059 if trailers != noHeader {
1060 enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "some-trailer"})
1061 }
1062 endStream = withData == false && trailers == noHeader
1063 send(resHeader)
1064 }
1065 if withData {
1066 endStream = trailers == noHeader
1067 ct.fr.WriteData(f.StreamID, endStream, []byte(resBody))
1068 }
1069 if trailers != noHeader {
1070 endStream = true
1071 buf.Reset()
1072 enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "some-value"})
1073 send(trailers)
1074 }
Brad Fitzpatricke90d6d02016-07-15 16:59:30 +00001075 if endStream {
1076 return nil
1077 }
1078 case *HeadersFrame:
1079 if expect100Continue != noHeader {
1080 buf.Reset()
1081 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"})
1082 send(expect100Continue)
1083 }
Brad Fitzpatrick520af5d2016-01-07 02:53:08 +00001084 }
1085 }
1086 }
1087 ct.run()
1088}
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001089
Blake Mizerany0e6d34e2016-01-09 15:16:57 -08001090func TestTransportReceiveUndeclaredTrailer(t *testing.T) {
1091 ct := newClientTester(t)
1092 ct.client = func() error {
1093 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
1094 res, err := ct.tr.RoundTrip(req)
1095 if err != nil {
1096 return fmt.Errorf("RoundTrip: %v", err)
1097 }
1098 defer res.Body.Close()
1099 if res.StatusCode != 200 {
1100 return fmt.Errorf("status code = %v; want 200", res.StatusCode)
1101 }
1102 slurp, err := ioutil.ReadAll(res.Body)
1103 if err != nil {
1104 return fmt.Errorf("res.Body ReadAll error = %q, %v; want %v", slurp, err, nil)
1105 }
1106 if len(slurp) > 0 {
1107 return fmt.Errorf("body = %q; want nothing", slurp)
1108 }
1109 if _, ok := res.Trailer["Some-Trailer"]; !ok {
1110 return fmt.Errorf("expected Some-Trailer")
1111 }
1112 return nil
1113 }
1114 ct.server = func() error {
1115 ct.greet()
1116
1117 var n int
1118 var hf *HeadersFrame
1119 for hf == nil && n < 10 {
1120 f, err := ct.fr.ReadFrame()
1121 if err != nil {
1122 return err
1123 }
1124 hf, _ = f.(*HeadersFrame)
1125 n++
1126 }
1127
1128 var buf bytes.Buffer
1129 enc := hpack.NewEncoder(&buf)
1130
1131 // send headers without Trailer header
1132 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1133 ct.fr.WriteHeaders(HeadersFrameParam{
1134 StreamID: hf.StreamID,
1135 EndHeaders: true,
1136 EndStream: false,
1137 BlockFragment: buf.Bytes(),
1138 })
1139
1140 // send trailers
1141 buf.Reset()
1142 enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "I'm an undeclared Trailer!"})
1143 ct.fr.WriteHeaders(HeadersFrameParam{
1144 StreamID: hf.StreamID,
1145 EndHeaders: true,
1146 EndStream: true,
1147 BlockFragment: buf.Bytes(),
1148 })
1149 return nil
1150 }
1151 ct.run()
1152}
1153
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001154func TestTransportInvalidTrailer_Pseudo1(t *testing.T) {
1155 testTransportInvalidTrailer_Pseudo(t, oneHeader)
1156}
1157func TestTransportInvalidTrailer_Pseudo2(t *testing.T) {
1158 testTransportInvalidTrailer_Pseudo(t, splitHeader)
1159}
1160func testTransportInvalidTrailer_Pseudo(t *testing.T, trailers headerType) {
Brad Fitzpatrick9e1fb3c2016-02-20 14:24:27 +05301161 testInvalidTrailer(t, trailers, pseudoHeaderError(":colon"), func(enc *hpack.Encoder) {
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001162 enc.WriteField(hpack.HeaderField{Name: ":colon", Value: "foo"})
1163 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
1164 })
1165}
1166
1167func TestTransportInvalidTrailer_Capital1(t *testing.T) {
1168 testTransportInvalidTrailer_Capital(t, oneHeader)
1169}
1170func TestTransportInvalidTrailer_Capital2(t *testing.T) {
1171 testTransportInvalidTrailer_Capital(t, splitHeader)
1172}
1173func testTransportInvalidTrailer_Capital(t *testing.T, trailers headerType) {
Brad Fitzpatrick9e1fb3c2016-02-20 14:24:27 +05301174 testInvalidTrailer(t, trailers, headerFieldNameError("Capital"), func(enc *hpack.Encoder) {
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001175 enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
1176 enc.WriteField(hpack.HeaderField{Name: "Capital", Value: "bad"})
1177 })
1178}
Brad Fitzpatrickb2ed34f2016-01-20 20:16:54 +00001179func TestTransportInvalidTrailer_EmptyFieldName(t *testing.T) {
Brad Fitzpatrick9e1fb3c2016-02-20 14:24:27 +05301180 testInvalidTrailer(t, oneHeader, headerFieldNameError(""), func(enc *hpack.Encoder) {
Brad Fitzpatrickb2ed34f2016-01-20 20:16:54 +00001181 enc.WriteField(hpack.HeaderField{Name: "", Value: "bad"})
1182 })
1183}
1184func TestTransportInvalidTrailer_BinaryFieldValue(t *testing.T) {
Brad Fitzpatrick9e1fb3c2016-02-20 14:24:27 +05301185 testInvalidTrailer(t, oneHeader, headerFieldValueError("has\nnewline"), func(enc *hpack.Encoder) {
1186 enc.WriteField(hpack.HeaderField{Name: "x", Value: "has\nnewline"})
Brad Fitzpatrickb2ed34f2016-01-20 20:16:54 +00001187 })
1188}
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001189
1190func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeTrailer func(*hpack.Encoder)) {
1191 ct := newClientTester(t)
1192 ct.client = func() error {
1193 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
1194 res, err := ct.tr.RoundTrip(req)
1195 if err != nil {
1196 return fmt.Errorf("RoundTrip: %v", err)
1197 }
1198 defer res.Body.Close()
1199 if res.StatusCode != 200 {
1200 return fmt.Errorf("status code = %v; want 200", res.StatusCode)
1201 }
1202 slurp, err := ioutil.ReadAll(res.Body)
1203 if err != wantErr {
Brad Fitzpatrick9e1fb3c2016-02-20 14:24:27 +05301204 return fmt.Errorf("res.Body ReadAll error = %q, %#v; want %T of %#v", slurp, err, wantErr, wantErr)
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001205 }
1206 if len(slurp) > 0 {
1207 return fmt.Errorf("body = %q; want nothing", slurp)
1208 }
1209 return nil
1210 }
1211 ct.server = func() error {
1212 ct.greet()
1213 var buf bytes.Buffer
1214 enc := hpack.NewEncoder(&buf)
1215
1216 for {
1217 f, err := ct.fr.ReadFrame()
1218 if err != nil {
1219 return err
1220 }
1221 switch f := f.(type) {
1222 case *HeadersFrame:
1223 var endStream bool
1224 send := func(mode headerType) {
1225 hbf := buf.Bytes()
1226 switch mode {
1227 case oneHeader:
1228 ct.fr.WriteHeaders(HeadersFrameParam{
1229 StreamID: f.StreamID,
1230 EndHeaders: true,
1231 EndStream: endStream,
1232 BlockFragment: hbf,
1233 })
1234 case splitHeader:
1235 if len(hbf) < 2 {
1236 panic("too small")
1237 }
1238 ct.fr.WriteHeaders(HeadersFrameParam{
1239 StreamID: f.StreamID,
1240 EndHeaders: false,
1241 EndStream: endStream,
1242 BlockFragment: hbf[:1],
1243 })
1244 ct.fr.WriteContinuation(f.StreamID, true, hbf[1:])
1245 default:
1246 panic("bogus mode")
1247 }
1248 }
1249 // Response headers (1+ frames; 1 or 2 in this test, but never 0)
1250 {
1251 buf.Reset()
1252 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1253 enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "declared"})
1254 endStream = false
1255 send(oneHeader)
1256 }
1257 // Trailers:
1258 {
1259 endStream = true
1260 buf.Reset()
1261 writeTrailer(enc)
1262 send(trailers)
1263 }
1264 return nil
1265 }
1266 }
1267 }
1268 ct.run()
1269}
1270
1271func TestTransportChecksResponseHeaderListSize(t *testing.T) {
1272 ct := newClientTester(t)
1273 ct.client = func() error {
1274 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
1275 res, err := ct.tr.RoundTrip(req)
1276 if err != errResponseHeaderListSize {
1277 if res != nil {
1278 res.Body.Close()
1279 }
1280 size := int64(0)
1281 for k, vv := range res.Header {
1282 for _, v := range vv {
1283 size += int64(len(k)) + int64(len(v)) + 32
1284 }
1285 }
1286 return fmt.Errorf("RoundTrip Error = %v (and %d bytes of response headers); want errResponseHeaderListSize", err, size)
1287 }
1288 return nil
1289 }
1290 ct.server = func() error {
1291 ct.greet()
1292 var buf bytes.Buffer
1293 enc := hpack.NewEncoder(&buf)
1294
1295 for {
1296 f, err := ct.fr.ReadFrame()
1297 if err != nil {
1298 return err
1299 }
1300 switch f := f.(type) {
1301 case *HeadersFrame:
1302 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1303 large := strings.Repeat("a", 1<<10)
1304 for i := 0; i < 5042; i++ {
1305 enc.WriteField(hpack.HeaderField{Name: large, Value: large})
1306 }
1307 if size, want := buf.Len(), 6329; size != want {
1308 // Note: this number might change if
1309 // our hpack implementation
1310 // changes. That's fine. This is
1311 // just a sanity check that our
1312 // response can fit in a single
1313 // header block fragment frame.
1314 return fmt.Errorf("encoding over 10MB of duplicate keypairs took %d bytes; expected %d", size, want)
1315 }
1316 ct.fr.WriteHeaders(HeadersFrameParam{
1317 StreamID: f.StreamID,
1318 EndHeaders: true,
1319 EndStream: true,
1320 BlockFragment: buf.Bytes(),
1321 })
1322 return nil
1323 }
1324 }
1325 }
1326 ct.run()
Brad Fitzpatrickf530c4e2016-01-07 08:16:00 -08001327}
Brad Fitzpatrick5df54832016-01-11 16:40:14 +00001328
1329// Test that the the Transport returns a typed error from Response.Body.Read calls
1330// when the server sends an error. (here we use a panic, since that should generate
1331// a stream error, but others like cancel should be similar)
1332func TestTransportBodyReadErrorType(t *testing.T) {
Brad Fitzpatrick341cd082016-01-13 21:09:49 +00001333 doPanic := make(chan bool, 1)
Brad Fitzpatrick5df54832016-01-11 16:40:14 +00001334 st := newServerTester(t,
1335 func(w http.ResponseWriter, r *http.Request) {
1336 w.(http.Flusher).Flush() // force headers out
Brad Fitzpatrick341cd082016-01-13 21:09:49 +00001337 <-doPanic
Brad Fitzpatrick5df54832016-01-11 16:40:14 +00001338 panic("boom")
1339 },
1340 optOnlyServer,
1341 optQuiet,
1342 )
1343 defer st.Close()
1344
1345 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1346 defer tr.CloseIdleConnections()
1347 c := &http.Client{Transport: tr}
1348
1349 res, err := c.Get(st.ts.URL)
1350 if err != nil {
1351 t.Fatal(err)
1352 }
1353 defer res.Body.Close()
Brad Fitzpatrick341cd082016-01-13 21:09:49 +00001354 doPanic <- true
Brad Fitzpatrick5df54832016-01-11 16:40:14 +00001355 buf := make([]byte, 100)
1356 n, err := res.Body.Read(buf)
1357 want := StreamError{StreamID: 0x1, Code: 0x2}
1358 if !reflect.DeepEqual(want, err) {
1359 t.Errorf("Read = %v, %#v; want error %#v", n, err, want)
1360 }
1361}
Brad Fitzpatrick76365a42016-01-12 19:24:09 +00001362
1363// golang.org/issue/13924
1364// This used to fail after many iterations, especially with -race:
1365// go test -v -run=TestTransportDoubleCloseOnWriteError -count=500 -race
1366func TestTransportDoubleCloseOnWriteError(t *testing.T) {
1367 var (
1368 mu sync.Mutex
1369 conn net.Conn // to close if set
1370 )
1371
1372 st := newServerTester(t,
1373 func(w http.ResponseWriter, r *http.Request) {
1374 mu.Lock()
1375 defer mu.Unlock()
1376 if conn != nil {
1377 conn.Close()
1378 }
1379 },
1380 optOnlyServer,
1381 )
1382 defer st.Close()
1383
1384 tr := &Transport{
1385 TLSClientConfig: tlsConfigInsecure,
1386 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
1387 tc, err := tls.Dial(network, addr, cfg)
1388 if err != nil {
1389 return nil, err
1390 }
1391 mu.Lock()
1392 defer mu.Unlock()
1393 conn = tc
1394 return tc, nil
1395 },
1396 }
1397 defer tr.CloseIdleConnections()
1398 c := &http.Client{Transport: tr}
1399 c.Get(st.ts.URL)
1400}
Brad Fitzpatrickf5de73e2016-01-19 03:50:30 +00001401
1402// Test that the http1 Transport.DisableKeepAlives option is respected
1403// and connections are closed as soon as idle.
1404// See golang.org/issue/14008
1405func TestTransportDisableKeepAlives(t *testing.T) {
1406 st := newServerTester(t,
1407 func(w http.ResponseWriter, r *http.Request) {
1408 io.WriteString(w, "hi")
1409 },
1410 optOnlyServer,
1411 )
1412 defer st.Close()
1413
1414 connClosed := make(chan struct{}) // closed on tls.Conn.Close
1415 tr := &Transport{
1416 t1: &http.Transport{
1417 DisableKeepAlives: true,
1418 },
1419 TLSClientConfig: tlsConfigInsecure,
1420 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
1421 tc, err := tls.Dial(network, addr, cfg)
1422 if err != nil {
1423 return nil, err
1424 }
1425 return &noteCloseConn{Conn: tc, closefn: func() { close(connClosed) }}, nil
1426 },
1427 }
1428 c := &http.Client{Transport: tr}
1429 res, err := c.Get(st.ts.URL)
1430 if err != nil {
1431 t.Fatal(err)
1432 }
1433 if _, err := ioutil.ReadAll(res.Body); err != nil {
1434 t.Fatal(err)
1435 }
1436 defer res.Body.Close()
1437
1438 select {
1439 case <-connClosed:
1440 case <-time.After(1 * time.Second):
1441 t.Errorf("timeout")
1442 }
1443
1444}
1445
1446// Test concurrent requests with Transport.DisableKeepAlives. We can share connections,
1447// but when things are totally idle, it still needs to close.
1448func TestTransportDisableKeepAlives_Concurrency(t *testing.T) {
1449 const D = 25 * time.Millisecond
1450 st := newServerTester(t,
1451 func(w http.ResponseWriter, r *http.Request) {
1452 time.Sleep(D)
1453 io.WriteString(w, "hi")
1454 },
1455 optOnlyServer,
1456 )
1457 defer st.Close()
1458
1459 var dials int32
1460 var conns sync.WaitGroup
1461 tr := &Transport{
1462 t1: &http.Transport{
1463 DisableKeepAlives: true,
1464 },
1465 TLSClientConfig: tlsConfigInsecure,
1466 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
1467 tc, err := tls.Dial(network, addr, cfg)
1468 if err != nil {
1469 return nil, err
1470 }
1471 atomic.AddInt32(&dials, 1)
1472 conns.Add(1)
1473 return &noteCloseConn{Conn: tc, closefn: func() { conns.Done() }}, nil
1474 },
1475 }
1476 c := &http.Client{Transport: tr}
1477 var reqs sync.WaitGroup
1478 const N = 20
1479 for i := 0; i < N; i++ {
1480 reqs.Add(1)
1481 if i == N-1 {
1482 // For the final request, try to make all the
1483 // others close. This isn't verified in the
1484 // count, other than the Log statement, since
1485 // it's so timing dependent. This test is
1486 // really to make sure we don't interrupt a
1487 // valid request.
1488 time.Sleep(D * 2)
1489 }
1490 go func() {
1491 defer reqs.Done()
1492 res, err := c.Get(st.ts.URL)
1493 if err != nil {
1494 t.Error(err)
1495 return
1496 }
1497 if _, err := ioutil.ReadAll(res.Body); err != nil {
1498 t.Error(err)
1499 return
1500 }
1501 res.Body.Close()
1502 }()
1503 }
1504 reqs.Wait()
1505 conns.Wait()
1506 t.Logf("did %d dials, %d requests", atomic.LoadInt32(&dials), N)
1507}
1508
1509type noteCloseConn struct {
1510 net.Conn
1511 onceClose sync.Once
1512 closefn func()
1513}
1514
1515func (c *noteCloseConn) Close() error {
1516 c.onceClose.Do(c.closefn)
1517 return c.Conn.Close()
1518}
1519
1520func isTimeout(err error) bool {
1521 switch err := err.(type) {
1522 case nil:
1523 return false
1524 case *url.Error:
1525 return isTimeout(err.Err)
1526 case net.Error:
1527 return err.Timeout()
1528 }
1529 return false
1530}
1531
1532// Test that the http1 Transport.ResponseHeaderTimeout option and cancel is sent.
1533func TestTransportResponseHeaderTimeout_NoBody(t *testing.T) {
1534 testTransportResponseHeaderTimeout(t, false)
1535}
1536func TestTransportResponseHeaderTimeout_Body(t *testing.T) {
1537 testTransportResponseHeaderTimeout(t, true)
1538}
1539
1540func testTransportResponseHeaderTimeout(t *testing.T, body bool) {
1541 ct := newClientTester(t)
1542 ct.tr.t1 = &http.Transport{
1543 ResponseHeaderTimeout: 5 * time.Millisecond,
1544 }
1545 ct.client = func() error {
1546 c := &http.Client{Transport: ct.tr}
1547 var err error
1548 var n int64
1549 const bodySize = 4 << 20
1550 if body {
1551 _, err = c.Post("https://dummy.tld/", "text/foo", io.LimitReader(countingReader{&n}, bodySize))
1552 } else {
1553 _, err = c.Get("https://dummy.tld/")
1554 }
1555 if !isTimeout(err) {
1556 t.Errorf("client expected timeout error; got %#v", err)
1557 }
1558 if body && n != bodySize {
1559 t.Errorf("only read %d bytes of body; want %d", n, bodySize)
1560 }
1561 return nil
1562 }
1563 ct.server = func() error {
1564 ct.greet()
1565 for {
1566 f, err := ct.fr.ReadFrame()
1567 if err != nil {
1568 t.Logf("ReadFrame: %v", err)
1569 return nil
1570 }
1571 switch f := f.(type) {
1572 case *DataFrame:
1573 dataLen := len(f.Data())
1574 if dataLen > 0 {
1575 if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
1576 return err
1577 }
1578 if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
1579 return err
1580 }
1581 }
1582 case *RSTStreamFrame:
1583 if f.StreamID == 1 && f.ErrCode == ErrCodeCancel {
1584 return nil
1585 }
1586 }
1587 }
Brad Fitzpatrickf5de73e2016-01-19 03:50:30 +00001588 }
1589 ct.run()
1590}
1591
1592func TestTransportDisableCompression(t *testing.T) {
1593 const body = "sup"
1594 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1595 want := http.Header{
1596 "User-Agent": []string{"Go-http-client/2.0"},
1597 }
1598 if !reflect.DeepEqual(r.Header, want) {
1599 t.Errorf("request headers = %v; want %v", r.Header, want)
1600 }
1601 }, optOnlyServer)
1602 defer st.Close()
1603
1604 tr := &Transport{
1605 TLSClientConfig: tlsConfigInsecure,
1606 t1: &http.Transport{
1607 DisableCompression: true,
1608 },
1609 }
1610 defer tr.CloseIdleConnections()
1611
1612 req, err := http.NewRequest("GET", st.ts.URL, nil)
1613 if err != nil {
1614 t.Fatal(err)
1615 }
1616 res, err := tr.RoundTrip(req)
1617 if err != nil {
1618 t.Fatal(err)
1619 }
1620 defer res.Body.Close()
1621}
Brad Fitzpatrick493a2622016-02-04 19:41:12 +00001622
1623// RFC 7540 section 8.1.2.2
1624func TestTransportRejectsConnHeaders(t *testing.T) {
1625 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1626 var got []string
1627 for k := range r.Header {
1628 got = append(got, k)
1629 }
1630 sort.Strings(got)
1631 w.Header().Set("Got-Header", strings.Join(got, ","))
1632 }, optOnlyServer)
1633 defer st.Close()
1634
1635 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1636 defer tr.CloseIdleConnections()
1637
1638 tests := []struct {
1639 key string
1640 value []string
1641 want string
1642 }{
1643 {
1644 key: "Upgrade",
1645 value: []string{"anything"},
1646 want: "ERROR: http2: invalid Upgrade request header",
1647 },
1648 {
1649 key: "Connection",
1650 value: []string{"foo"},
1651 want: "ERROR: http2: invalid Connection request header",
1652 },
1653 {
1654 key: "Connection",
1655 value: []string{"close"},
1656 want: "Accept-Encoding,User-Agent",
1657 },
1658 {
1659 key: "Connection",
1660 value: []string{"close", "something-else"},
1661 want: "ERROR: http2: invalid Connection request header",
1662 },
1663 {
1664 key: "Connection",
1665 value: []string{"keep-alive"},
1666 want: "Accept-Encoding,User-Agent",
1667 },
1668 {
1669 key: "Proxy-Connection", // just deleted and ignored
1670 value: []string{"keep-alive"},
1671 want: "Accept-Encoding,User-Agent",
1672 },
1673 {
1674 key: "Transfer-Encoding",
1675 value: []string{""},
1676 want: "Accept-Encoding,User-Agent",
1677 },
1678 {
1679 key: "Transfer-Encoding",
1680 value: []string{"foo"},
1681 want: "ERROR: http2: invalid Transfer-Encoding request header",
1682 },
1683 {
1684 key: "Transfer-Encoding",
1685 value: []string{"chunked"},
1686 want: "Accept-Encoding,User-Agent",
1687 },
1688 {
1689 key: "Transfer-Encoding",
1690 value: []string{"chunked", "other"},
1691 want: "ERROR: http2: invalid Transfer-Encoding request header",
1692 },
1693 {
1694 key: "Content-Length",
1695 value: []string{"123"},
1696 want: "Accept-Encoding,User-Agent",
1697 },
Roland Shoemaker024ed622016-04-03 12:24:15 -07001698 {
1699 key: "Keep-Alive",
1700 value: []string{"doop"},
1701 want: "Accept-Encoding,User-Agent",
1702 },
Brad Fitzpatrick493a2622016-02-04 19:41:12 +00001703 }
1704
1705 for _, tt := range tests {
1706 req, _ := http.NewRequest("GET", st.ts.URL, nil)
1707 req.Header[tt.key] = tt.value
1708 res, err := tr.RoundTrip(req)
1709 var got string
1710 if err != nil {
1711 got = fmt.Sprintf("ERROR: %v", err)
1712 } else {
1713 got = res.Header.Get("Got-Header")
1714 res.Body.Close()
1715 }
1716 if got != tt.want {
1717 t.Errorf("For key %q, value %q, got = %q; want %q", tt.key, tt.value, got, tt.want)
1718 }
1719 }
1720}
Brad Fitzpatrickcbbbe2b2016-02-13 01:55:36 +00001721
Brad Fitzpatrick5916dcb2016-05-18 23:19:24 +00001722// golang.org/issue/14048
1723func TestTransportFailsOnInvalidHeaders(t *testing.T) {
1724 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1725 var got []string
1726 for k := range r.Header {
1727 got = append(got, k)
1728 }
1729 sort.Strings(got)
1730 w.Header().Set("Got-Header", strings.Join(got, ","))
1731 }, optOnlyServer)
1732 defer st.Close()
1733
1734 tests := [...]struct {
1735 h http.Header
1736 wantErr string
1737 }{
1738 0: {
1739 h: http.Header{"with space": {"foo"}},
1740 wantErr: `invalid HTTP header name "with space"`,
1741 },
1742 1: {
1743 h: http.Header{"name": {"Брэд"}},
1744 wantErr: "", // okay
1745 },
1746 2: {
1747 h: http.Header{"имя": {"Brad"}},
1748 wantErr: `invalid HTTP header name "имя"`,
1749 },
1750 3: {
1751 h: http.Header{"foo": {"foo\x01bar"}},
1752 wantErr: `invalid HTTP header value "foo\x01bar" for header "foo"`,
1753 },
1754 }
1755
1756 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1757 defer tr.CloseIdleConnections()
1758
1759 for i, tt := range tests {
1760 req, _ := http.NewRequest("GET", st.ts.URL, nil)
1761 req.Header = tt.h
1762 res, err := tr.RoundTrip(req)
1763 var bad bool
1764 if tt.wantErr == "" {
1765 if err != nil {
1766 bad = true
1767 t.Errorf("case %d: error = %v; want no error", i, err)
1768 }
1769 } else {
1770 if !strings.Contains(fmt.Sprint(err), tt.wantErr) {
1771 bad = true
1772 t.Errorf("case %d: error = %v; want error %q", i, err, tt.wantErr)
1773 }
1774 }
1775 if err == nil {
1776 if bad {
1777 t.Logf("case %d: server got headers %q", i, res.Header.Get("Got-Header"))
1778 }
1779 res.Body.Close()
1780 }
1781 }
1782}
1783
Brad Fitzpatrickcbbbe2b2016-02-13 01:55:36 +00001784// Tests that gzipReader doesn't crash on a second Read call following
1785// the first Read call's gzip.NewReader returning an error.
1786func TestGzipReader_DoubleReadCrash(t *testing.T) {
1787 gz := &gzipReader{
1788 body: ioutil.NopCloser(strings.NewReader("0123456789")),
1789 }
1790 var buf [1]byte
1791 n, err1 := gz.Read(buf[:])
1792 if n != 0 || !strings.Contains(fmt.Sprint(err1), "invalid header") {
1793 t.Fatalf("Read = %v, %v; want 0, invalid header", n, err1)
1794 }
1795 n, err2 := gz.Read(buf[:])
1796 if n != 0 || err2 != err1 {
1797 t.Fatalf("second Read = %v, %v; want 0, %v", n, err2, err1)
1798 }
1799}
Brad Fitzpatrick3f5b0e62016-02-25 18:11:36 +00001800
1801func TestTransportNewTLSConfig(t *testing.T) {
1802 tests := [...]struct {
1803 conf *tls.Config
1804 host string
1805 want *tls.Config
1806 }{
1807 // Normal case.
1808 0: {
1809 conf: nil,
1810 host: "foo.com",
1811 want: &tls.Config{
1812 ServerName: "foo.com",
1813 NextProtos: []string{NextProtoTLS},
1814 },
1815 },
1816
1817 // User-provided name (bar.com) takes precedence:
1818 1: {
1819 conf: &tls.Config{
1820 ServerName: "bar.com",
1821 },
1822 host: "foo.com",
1823 want: &tls.Config{
1824 ServerName: "bar.com",
1825 NextProtos: []string{NextProtoTLS},
1826 },
1827 },
1828
1829 // NextProto is prepended:
1830 2: {
1831 conf: &tls.Config{
1832 NextProtos: []string{"foo", "bar"},
1833 },
1834 host: "example.com",
1835 want: &tls.Config{
1836 ServerName: "example.com",
1837 NextProtos: []string{NextProtoTLS, "foo", "bar"},
1838 },
1839 },
1840
1841 // NextProto is not duplicated:
1842 3: {
1843 conf: &tls.Config{
1844 NextProtos: []string{"foo", "bar", NextProtoTLS},
1845 },
1846 host: "example.com",
1847 want: &tls.Config{
1848 ServerName: "example.com",
1849 NextProtos: []string{"foo", "bar", NextProtoTLS},
1850 },
1851 },
1852 }
1853 for i, tt := range tests {
1854 tr := &Transport{TLSClientConfig: tt.conf}
1855 got := tr.newTLSConfig(tt.host)
1856 if !reflect.DeepEqual(got, tt.want) {
1857 t.Errorf("%d. got %#v; want %#v", i, got, tt.want)
1858 }
1859 }
1860}
Brad Fitzpatrick991d3e32016-03-24 11:19:19 +11001861
1862// The Google GFE responds to HEAD requests with a HEADERS frame
1863// without END_STREAM, followed by a 0-length DATA frame with
1864// END_STREAM. Make sure we don't get confused by that. (We did.)
1865func TestTransportReadHeadResponse(t *testing.T) {
1866 ct := newClientTester(t)
1867 clientDone := make(chan struct{})
1868 ct.client = func() error {
1869 defer close(clientDone)
1870 req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
1871 res, err := ct.tr.RoundTrip(req)
1872 if err != nil {
1873 return err
1874 }
1875 if res.ContentLength != 123 {
1876 return fmt.Errorf("Content-Length = %d; want 123", res.ContentLength)
1877 }
1878 slurp, err := ioutil.ReadAll(res.Body)
1879 if err != nil {
1880 return fmt.Errorf("ReadAll: %v", err)
1881 }
1882 if len(slurp) > 0 {
1883 return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
1884 }
1885 return nil
1886 }
1887 ct.server = func() error {
1888 ct.greet()
1889 for {
1890 f, err := ct.fr.ReadFrame()
1891 if err != nil {
1892 t.Logf("ReadFrame: %v", err)
1893 return nil
1894 }
1895 hf, ok := f.(*HeadersFrame)
1896 if !ok {
1897 continue
1898 }
1899 var buf bytes.Buffer
1900 enc := hpack.NewEncoder(&buf)
1901 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
1902 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
1903 ct.fr.WriteHeaders(HeadersFrameParam{
1904 StreamID: hf.StreamID,
1905 EndHeaders: true,
1906 EndStream: false, // as the GFE does
1907 BlockFragment: buf.Bytes(),
1908 })
1909 ct.fr.WriteData(hf.StreamID, true, nil)
1910
1911 <-clientDone
1912 return nil
1913 }
Brad Fitzpatrick991d3e32016-03-24 11:19:19 +11001914 }
1915 ct.run()
1916}
Brad Fitzpatrick4d07e8a2016-05-20 18:55:47 +00001917
1918type neverEnding byte
1919
1920func (b neverEnding) Read(p []byte) (int, error) {
1921 for i := range p {
1922 p[i] = byte(b)
1923 }
1924 return len(p), nil
1925}
1926
1927// golang.org/issue/15425: test that a handler closing the request
1928// body doesn't terminate the stream to the peer. (It just stops
1929// readability from the handler's side, and eventually the client
1930// runs out of flow control tokens)
1931func TestTransportHandlerBodyClose(t *testing.T) {
1932 const bodySize = 10 << 20
1933 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1934 r.Body.Close()
1935 io.Copy(w, io.LimitReader(neverEnding('A'), bodySize))
1936 }, optOnlyServer)
1937 defer st.Close()
1938
1939 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1940 defer tr.CloseIdleConnections()
1941
1942 g0 := runtime.NumGoroutine()
1943
1944 const numReq = 10
1945 for i := 0; i < numReq; i++ {
1946 req, err := http.NewRequest("POST", st.ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
1947 if err != nil {
1948 t.Fatal(err)
1949 }
1950 res, err := tr.RoundTrip(req)
1951 if err != nil {
1952 t.Fatal(err)
1953 }
1954 n, err := io.Copy(ioutil.Discard, res.Body)
1955 res.Body.Close()
1956 if n != bodySize || err != nil {
Mikio Haradfd9ed62016-05-26 10:07:17 +09001957 t.Fatalf("req#%d: Copy = %d, %v; want %d, nil", i, n, err, bodySize)
Brad Fitzpatrick4d07e8a2016-05-20 18:55:47 +00001958 }
1959 }
1960 tr.CloseIdleConnections()
1961
1962 gd := runtime.NumGoroutine() - g0
1963 if gd > numReq/2 {
1964 t.Errorf("appeared to leak goroutines")
1965 }
1966
1967}
Andrew Gerrand154d9f92016-06-06 15:43:46 +10001968
1969// https://golang.org/issue/15930
1970func TestTransportFlowControl(t *testing.T) {
1971 const (
1972 total = 100 << 20 // 100MB
1973 bufLen = 1 << 16
1974 )
1975
1976 var wrote int64 // updated atomically
1977 st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1978 b := make([]byte, bufLen)
1979 for wrote < total {
1980 n, err := w.Write(b)
1981 atomic.AddInt64(&wrote, int64(n))
1982 if err != nil {
1983 t.Errorf("ResponseWriter.Write error: %v", err)
1984 break
1985 }
1986 w.(http.Flusher).Flush()
1987 }
1988 }, optOnlyServer)
1989
1990 tr := &Transport{TLSClientConfig: tlsConfigInsecure}
1991 defer tr.CloseIdleConnections()
1992 req, err := http.NewRequest("GET", st.ts.URL, nil)
1993 if err != nil {
1994 t.Fatal("NewRequest error:", err)
1995 }
1996 resp, err := tr.RoundTrip(req)
1997 if err != nil {
1998 t.Fatal("RoundTrip error:", err)
1999 }
2000 defer resp.Body.Close()
2001
2002 var read int64
2003 b := make([]byte, bufLen)
2004 for {
2005 n, err := resp.Body.Read(b)
2006 if err == io.EOF {
2007 break
2008 }
2009 if err != nil {
2010 t.Fatal("Read error:", err)
2011 }
2012 read += int64(n)
2013
2014 const max = transportDefaultStreamFlow
2015 if w := atomic.LoadInt64(&wrote); -max > read-w || read-w > max {
2016 t.Fatalf("Too much data inflight: server wrote %v bytes but client only received %v", w, read)
2017 }
2018
2019 // Let the server get ahead of the client.
2020 time.Sleep(1 * time.Millisecond)
2021 }
2022}
Brad Fitzpatrickef2e00e2016-06-28 16:00:16 -07002023
2024// golang.org/issue/14627 -- if the server sends a GOAWAY frame, make
2025// the Transport remember it and return it back to users (via
2026// RoundTrip or request body reads) if needed (e.g. if the server
2027// proceeds to close the TCP connection before the client gets its
2028// response)
2029func TestTransportUsesGoAwayDebugError_RoundTrip(t *testing.T) {
2030 testTransportUsesGoAwayDebugError(t, false)
2031}
2032
2033func TestTransportUsesGoAwayDebugError_Body(t *testing.T) {
2034 testTransportUsesGoAwayDebugError(t, true)
2035}
2036
2037func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) {
2038 ct := newClientTester(t)
2039 clientDone := make(chan struct{})
2040
2041 const goAwayErrCode = ErrCodeHTTP11Required // arbitrary
2042 const goAwayDebugData = "some debug data"
2043
2044 ct.client = func() error {
2045 defer close(clientDone)
2046 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2047 res, err := ct.tr.RoundTrip(req)
2048 if failMidBody {
2049 if err != nil {
2050 return fmt.Errorf("unexpected client RoundTrip error: %v", err)
2051 }
2052 _, err = io.Copy(ioutil.Discard, res.Body)
2053 res.Body.Close()
2054 }
2055 want := GoAwayError{
Brad Fitzpatrick8e573f42016-06-29 11:55:36 -07002056 LastStreamID: 5,
Brad Fitzpatrickef2e00e2016-06-28 16:00:16 -07002057 ErrCode: goAwayErrCode,
2058 DebugData: goAwayDebugData,
2059 }
2060 if !reflect.DeepEqual(err, want) {
2061 t.Errorf("RoundTrip error = %T: %#v, want %T (%#T)", err, err, want, want)
2062 }
2063 return nil
2064 }
2065 ct.server = func() error {
2066 ct.greet()
2067 for {
2068 f, err := ct.fr.ReadFrame()
2069 if err != nil {
2070 t.Logf("ReadFrame: %v", err)
2071 return nil
2072 }
2073 hf, ok := f.(*HeadersFrame)
2074 if !ok {
2075 continue
2076 }
2077 if failMidBody {
2078 var buf bytes.Buffer
2079 enc := hpack.NewEncoder(&buf)
2080 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2081 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
2082 ct.fr.WriteHeaders(HeadersFrameParam{
2083 StreamID: hf.StreamID,
2084 EndHeaders: true,
2085 EndStream: false,
2086 BlockFragment: buf.Bytes(),
2087 })
2088 }
Brad Fitzpatrick8e573f42016-06-29 11:55:36 -07002089 // Write two GOAWAY frames, to test that the Transport takes
2090 // the interesting parts of both.
2091 ct.fr.WriteGoAway(5, ErrCodeNo, []byte(goAwayDebugData))
2092 ct.fr.WriteGoAway(5, goAwayErrCode, nil)
Brad Fitzpatrickef2e00e2016-06-28 16:00:16 -07002093 ct.sc.Close()
2094 <-clientDone
2095 return nil
2096 }
2097 }
2098 ct.run()
2099}
Brad Fitzpatrick6a513af2016-07-26 10:19:14 +02002100
2101// See golang.org/issue/16481
2102func TestTransportReturnsUnusedFlowControl(t *testing.T) {
2103 ct := newClientTester(t)
2104
2105 clientClosed := make(chan bool, 1)
2106 serverWroteBody := make(chan bool, 1)
2107
2108 ct.client = func() error {
2109 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2110 res, err := ct.tr.RoundTrip(req)
2111 if err != nil {
2112 return err
2113 }
2114 <-serverWroteBody
2115
2116 if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 {
2117 return fmt.Errorf("body read = %v, %v; want 1, nil", n, err)
2118 }
2119 res.Body.Close() // leaving 4999 bytes unread
2120 clientClosed <- true
2121
2122 return nil
2123 }
2124 ct.server = func() error {
2125 ct.greet()
2126
2127 var hf *HeadersFrame
2128 for {
2129 f, err := ct.fr.ReadFrame()
2130 if err != nil {
2131 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
2132 }
2133 switch f.(type) {
2134 case *WindowUpdateFrame, *SettingsFrame:
2135 continue
2136 }
2137 var ok bool
2138 hf, ok = f.(*HeadersFrame)
2139 if !ok {
2140 return fmt.Errorf("Got %T; want HeadersFrame", f)
2141 }
2142 break
2143 }
2144
2145 var buf bytes.Buffer
2146 enc := hpack.NewEncoder(&buf)
2147 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2148 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"})
2149 ct.fr.WriteHeaders(HeadersFrameParam{
2150 StreamID: hf.StreamID,
2151 EndHeaders: true,
2152 EndStream: false,
2153 BlockFragment: buf.Bytes(),
2154 })
2155 ct.fr.WriteData(hf.StreamID, false, make([]byte, 5000)) // without ending stream
2156 serverWroteBody <- true
2157
2158 <-clientClosed
2159
2160 f, err := ct.fr.ReadFrame()
2161 if err != nil {
2162 return fmt.Errorf("ReadFrame while waiting for RSTStreamFrame: %v", err)
2163 }
2164 if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel {
2165 return fmt.Errorf("Expected a WindowUpdateFrame with code cancel; got %v", summarizeFrame(f))
2166 }
2167
2168 // And wait for our flow control tokens back:
2169 f, err = ct.fr.ReadFrame()
2170 if err != nil {
2171 return fmt.Errorf("ReadFrame while waiting for WindowUpdateFrame: %v", err)
2172 }
2173 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != 4999 {
2174 return fmt.Errorf("Expected WindowUpdateFrame for 4999 bytes; got %v", summarizeFrame(f))
2175 }
2176 return nil
2177 }
2178 ct.run()
2179}
Brad Fitzpatrick35028a42016-07-31 15:09:09 -07002180
2181// See golang.org/issue/16556
2182func TestTransportReturnsDataPaddingFlowControl(t *testing.T) {
2183 ct := newClientTester(t)
2184
2185 unblockClient := make(chan bool, 1)
2186
2187 ct.client = func() error {
2188 req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
2189 res, err := ct.tr.RoundTrip(req)
2190 if err != nil {
2191 return err
2192 }
2193 defer res.Body.Close()
2194 <-unblockClient
2195 return nil
2196 }
2197 ct.server = func() error {
2198 ct.greet()
2199
2200 var hf *HeadersFrame
2201 for {
2202 f, err := ct.fr.ReadFrame()
2203 if err != nil {
2204 return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
2205 }
2206 switch f.(type) {
2207 case *WindowUpdateFrame, *SettingsFrame:
2208 continue
2209 }
2210 var ok bool
2211 hf, ok = f.(*HeadersFrame)
2212 if !ok {
2213 return fmt.Errorf("Got %T; want HeadersFrame", f)
2214 }
2215 break
2216 }
2217
2218 var buf bytes.Buffer
2219 enc := hpack.NewEncoder(&buf)
2220 enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
2221 enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"})
2222 ct.fr.WriteHeaders(HeadersFrameParam{
2223 StreamID: hf.StreamID,
2224 EndHeaders: true,
2225 EndStream: false,
2226 BlockFragment: buf.Bytes(),
2227 })
2228 pad := []byte("12345")
2229 ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream
2230
2231 f, err := ct.fr.ReadFrame()
2232 if err != nil {
2233 return fmt.Errorf("ReadFrame while waiting for first WindowUpdateFrame: %v", err)
2234 }
2235 wantBack := uint32(len(pad)) + 1 // one byte for the length of the padding
2236 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID != 0 {
2237 return fmt.Errorf("Expected conn WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f))
2238 }
2239
2240 f, err = ct.fr.ReadFrame()
2241 if err != nil {
2242 return fmt.Errorf("ReadFrame while waiting for second WindowUpdateFrame: %v", err)
2243 }
2244 if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID == 0 {
2245 return fmt.Errorf("Expected stream WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f))
2246 }
2247 unblockClient <- true
2248 return nil
2249 }
2250 ct.run()
2251}