Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / integration-tests / nghttpx_http2_test.go
1 package nghttp2
2
3 import (
4         "crypto/tls"
5         "fmt"
6         "github.com/bradfitz/http2"
7         "github.com/bradfitz/http2/hpack"
8         "io"
9         "io/ioutil"
10         "net/http"
11         "strings"
12         "syscall"
13         "testing"
14 )
15
16 // TestH2H1PlainGET tests whether simple HTTP/2 GET request works.
17 func TestH2H1PlainGET(t *testing.T) {
18         st := newServerTester(nil, t, noopHandler)
19         defer st.Close()
20
21         res, err := st.http2(requestParam{
22                 name: "TestH2H1PlainGET",
23         })
24         if err != nil {
25                 t.Fatalf("Error st.http2() = %v", err)
26         }
27
28         want := 200
29         if res.status != want {
30                 t.Errorf("status = %v; want %v", res.status, want)
31         }
32 }
33
34 // TestH2H1AddXff tests that server generates X-Forwarded-For header
35 // field when forwarding request to backend.
36 func TestH2H1AddXff(t *testing.T) {
37         st := newServerTester([]string{"--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
38                 xff := r.Header.Get("X-Forwarded-For")
39                 want := "127.0.0.1"
40                 if xff != want {
41                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
42                 }
43         })
44         defer st.Close()
45
46         _, err := st.http2(requestParam{
47                 name: "TestH2H1AddXff",
48         })
49         if err != nil {
50                 t.Fatalf("Error st.http2() = %v", err)
51         }
52 }
53
54 // TestH2H1AddXff2 tests that server appends X-Forwarded-For header
55 // field to existing one when forwarding request to backend.
56 func TestH2H1AddXff2(t *testing.T) {
57         st := newServerTester([]string{"--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
58                 xff := r.Header.Get("X-Forwarded-For")
59                 want := "host, 127.0.0.1"
60                 if xff != want {
61                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
62                 }
63         })
64         defer st.Close()
65
66         _, err := st.http2(requestParam{
67                 name: "TestH2H1AddXff2",
68                 header: []hpack.HeaderField{
69                         pair("x-forwarded-for", "host"),
70                 },
71         })
72         if err != nil {
73                 t.Fatalf("Error st.http2() = %v", err)
74         }
75 }
76
77 // TestH2H1StripXff tests that --strip-incoming-x-forwarded-for
78 // option.
79 func TestH2H1StripXff(t *testing.T) {
80         st := newServerTester([]string{"--strip-incoming-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
81                 if xff, found := r.Header["X-Forwarded-For"]; found {
82                         t.Errorf("X-Forwarded-For = %v; want nothing", xff)
83                 }
84         })
85         defer st.Close()
86
87         _, err := st.http2(requestParam{
88                 name: "TestH2H1StripXff1",
89                 header: []hpack.HeaderField{
90                         pair("x-forwarded-for", "host"),
91                 },
92         })
93         if err != nil {
94                 t.Fatalf("Error st.http2() = %v", err)
95         }
96 }
97
98 // TestH2H1StripAddXff tests that --strip-incoming-x-forwarded-for and
99 // --add-x-forwarded-for options.
100 func TestH2H1StripAddXff(t *testing.T) {
101         args := []string{
102                 "--strip-incoming-x-forwarded-for",
103                 "--add-x-forwarded-for",
104         }
105         st := newServerTester(args, t, func(w http.ResponseWriter, r *http.Request) {
106                 xff := r.Header.Get("X-Forwarded-For")
107                 want := "127.0.0.1"
108                 if xff != want {
109                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
110                 }
111         })
112         defer st.Close()
113
114         _, err := st.http2(requestParam{
115                 name: "TestH2H1StripAddXff",
116                 header: []hpack.HeaderField{
117                         pair("x-forwarded-for", "host"),
118                 },
119         })
120         if err != nil {
121                 t.Fatalf("Error st.http2() = %v", err)
122         }
123 }
124
125 // TestH2H1GenerateVia tests that server generates Via header field to and
126 // from backend server.
127 func TestH2H1GenerateVia(t *testing.T) {
128         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
129                 if got, want := r.Header.Get("Via"), "2 nghttpx"; got != want {
130                         t.Errorf("Via: %v; want %v", got, want)
131                 }
132         })
133         defer st.Close()
134
135         res, err := st.http2(requestParam{
136                 name: "TestH2H1GenerateVia",
137         })
138         if err != nil {
139                 t.Fatalf("Error st.http2() = %v", err)
140         }
141         if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
142                 t.Errorf("Via: %v; want %v", got, want)
143         }
144 }
145
146 // TestH2H1AppendVia tests that server adds value to existing Via
147 // header field to and from backend server.
148 func TestH2H1AppendVia(t *testing.T) {
149         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
150                 if got, want := r.Header.Get("Via"), "foo, 2 nghttpx"; got != want {
151                         t.Errorf("Via: %v; want %v", got, want)
152                 }
153                 w.Header().Add("Via", "bar")
154         })
155         defer st.Close()
156
157         res, err := st.http2(requestParam{
158                 name: "TestH2H1AppendVia",
159                 header: []hpack.HeaderField{
160                         pair("via", "foo"),
161                 },
162         })
163         if err != nil {
164                 t.Fatalf("Error st.http2() = %v", err)
165         }
166         if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
167                 t.Errorf("Via: %v; want %v", got, want)
168         }
169 }
170
171 // TestH2H1NoVia tests that server does not add value to existing Via
172 // header field to and from backend server.
173 func TestH2H1NoVia(t *testing.T) {
174         st := newServerTester([]string{"--no-via"}, t, func(w http.ResponseWriter, r *http.Request) {
175                 if got, want := r.Header.Get("Via"), "foo"; got != want {
176                         t.Errorf("Via: %v; want %v", got, want)
177                 }
178                 w.Header().Add("Via", "bar")
179         })
180         defer st.Close()
181
182         res, err := st.http2(requestParam{
183                 name: "TestH2H1NoVia",
184                 header: []hpack.HeaderField{
185                         pair("via", "foo"),
186                 },
187         })
188         if err != nil {
189                 t.Fatalf("Error st.http2() = %v", err)
190         }
191         if got, want := res.header.Get("Via"), "bar"; got != want {
192                 t.Errorf("Via: %v; want %v", got, want)
193         }
194 }
195
196 // TestH2H1HostRewrite tests that server rewrites host header field
197 func TestH2H1HostRewrite(t *testing.T) {
198         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
199                 w.Header().Add("request-host", r.Host)
200         })
201         defer st.Close()
202
203         res, err := st.http2(requestParam{
204                 name: "TestH2H1HostRewrite",
205         })
206         if err != nil {
207                 t.Fatalf("Error st.http2() = %v", err)
208         }
209         if got, want := res.status, 200; got != want {
210                 t.Errorf("status: %v; want %v", got, want)
211         }
212         if got, want := res.header.Get("request-host"), st.backendHost; got != want {
213                 t.Errorf("request-host: %v; want %v", got, want)
214         }
215 }
216
217 // TestH2H1NoHostRewrite tests that server does not rewrite host
218 // header field
219 func TestH2H1NoHostRewrite(t *testing.T) {
220         st := newServerTester([]string{"--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
221                 w.Header().Add("request-host", r.Host)
222         })
223         defer st.Close()
224
225         res, err := st.http2(requestParam{
226                 name: "TestH2H1NoHostRewrite",
227         })
228         if err != nil {
229                 t.Fatalf("Error st.http2() = %v", err)
230         }
231         if got, want := res.status, 200; got != want {
232                 t.Errorf("status: %v; want %v", got, want)
233         }
234         if got, want := res.header.Get("request-host"), st.frontendHost; got != want {
235                 t.Errorf("request-host: %v; want %v", got, want)
236         }
237 }
238
239 // TestH2H1BadRequestCL tests that server rejects request whose
240 // content-length header field value does not match its request body
241 // size.
242 func TestH2H1BadRequestCL(t *testing.T) {
243         st := newServerTester(nil, t, noopHandler)
244         defer st.Close()
245
246         // we set content-length: 1024, but the actual request body is
247         // 3 bytes.
248         res, err := st.http2(requestParam{
249                 name:   "TestH2H1BadRequestCL",
250                 method: "POST",
251                 header: []hpack.HeaderField{
252                         pair("content-length", "1024"),
253                 },
254                 body: []byte("foo"),
255         })
256         if err != nil {
257                 t.Fatalf("Error st.http2() = %v", err)
258         }
259
260         want := http2.ErrCodeProtocol
261         if res.errCode != want {
262                 t.Errorf("res.errCode = %v; want %v", res.errCode, want)
263         }
264 }
265
266 // TestH2H1BadResponseCL tests that server returns error when
267 // content-length response header field value does not match its
268 // response body size.
269 func TestH2H1BadResponseCL(t *testing.T) {
270         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
271                 // we set content-length: 1024, but only send 3 bytes.
272                 w.Header().Add("Content-Length", "1024")
273                 w.Write([]byte("foo"))
274         })
275         defer st.Close()
276
277         res, err := st.http2(requestParam{
278                 name: "TestH2H1BadResponseCL",
279         })
280         if err != nil {
281                 t.Fatalf("Error st.http2() = %v", err)
282         }
283
284         want := http2.ErrCodeProtocol
285         if res.errCode != want {
286                 t.Errorf("res.errCode = %v; want %v", res.errCode, want)
287         }
288 }
289
290 // TestH2H1LocationRewrite tests location header field rewriting
291 // works.
292 func TestH2H1LocationRewrite(t *testing.T) {
293         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
294                 // TODO we cannot get st.ts's port number here.. 8443
295                 // is just a place holder.  We ignore it on rewrite.
296                 w.Header().Add("Location", "http://127.0.0.1:8443/p/q?a=b#fragment")
297         })
298         defer st.Close()
299
300         res, err := st.http2(requestParam{
301                 name: "TestH2H1LocationRewrite",
302         })
303         if err != nil {
304                 t.Fatalf("Error st.http2() = %v", err)
305         }
306
307         want := fmt.Sprintf("http://127.0.0.1:%v/p/q?a=b#fragment", serverPort)
308         if got := res.header.Get("Location"); got != want {
309                 t.Errorf("Location: %v; want %v", got, want)
310         }
311 }
312
313 // TestH2H1ChunkedRequestBody tests that chunked request body works.
314 func TestH2H1ChunkedRequestBody(t *testing.T) {
315         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
316                 want := "[chunked]"
317                 if got := fmt.Sprint(r.TransferEncoding); got != want {
318                         t.Errorf("Transfer-Encoding: %v; want %v", got, want)
319                 }
320                 body, err := ioutil.ReadAll(r.Body)
321                 if err != nil {
322                         t.Fatalf("Error reading r.body: %v", err)
323                 }
324                 want = "foo"
325                 if got := string(body); got != want {
326                         t.Errorf("body: %v; want %v", got, want)
327                 }
328         })
329         defer st.Close()
330
331         _, err := st.http2(requestParam{
332                 name:   "TestH2H1ChunkedRequestBody",
333                 method: "POST",
334                 body:   []byte("foo"),
335         })
336         if err != nil {
337                 t.Fatalf("Error st.http2() = %v", err)
338         }
339 }
340
341 // TestH2H1MultipleRequestCL tests that server rejects request with
342 // multiple Content-Length request header fields.
343 func TestH2H1MultipleRequestCL(t *testing.T) {
344         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
345                 t.Errorf("server should not forward bad request")
346         })
347         defer st.Close()
348
349         res, err := st.http2(requestParam{
350                 name: "TestH2H1MultipleRequestCL",
351                 header: []hpack.HeaderField{
352                         pair("content-length", "1"),
353                         pair("content-length", "1"),
354                 },
355         })
356         if err != nil {
357                 t.Fatalf("Error st.http2() = %v", err)
358         }
359         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
360                 t.Errorf("res.errCode: %v; want %v", got, want)
361         }
362 }
363
364 // TestH2H1InvalidRequestCL tests that server rejects request with
365 // Content-Length which cannot be parsed as a number.
366 func TestH2H1InvalidRequestCL(t *testing.T) {
367         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
368                 t.Errorf("server should not forward bad request")
369         })
370         defer st.Close()
371
372         res, err := st.http2(requestParam{
373                 name: "TestH2H1InvalidRequestCL",
374                 header: []hpack.HeaderField{
375                         pair("content-length", ""),
376                 },
377         })
378         if err != nil {
379                 t.Fatalf("Error st.http2() = %v", err)
380         }
381         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
382                 t.Errorf("res.errCode: %v; want %v", got, want)
383         }
384 }
385
386 // TestH2H1ConnectFailure tests that server handles the situation that
387 // connection attempt to HTTP/1 backend failed.
388 func TestH2H1ConnectFailure(t *testing.T) {
389         st := newServerTester(nil, t, noopHandler)
390         defer st.Close()
391
392         // shutdown backend server to simulate backend connect failure
393         st.ts.Close()
394
395         res, err := st.http2(requestParam{
396                 name: "TestH2H1ConnectFailure",
397         })
398         if err != nil {
399                 t.Fatalf("Error st.http2() = %v", err)
400         }
401         want := 503
402         if got := res.status; got != want {
403                 t.Errorf("status: %v; want %v", got, want)
404         }
405 }
406
407 // TestH2H1AssembleCookies tests that crumbled cookies in HTTP/2
408 // request is assembled into 1 when forwarding to HTTP/1 backend link.
409 func TestH2H1AssembleCookies(t *testing.T) {
410         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
411                 if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
412                         t.Errorf("Cookie: %v; want %v", got, want)
413                 }
414         })
415         defer st.Close()
416
417         res, err := st.http2(requestParam{
418                 name: "TestH2H1AssembleCookies",
419                 header: []hpack.HeaderField{
420                         pair("cookie", "alpha"),
421                         pair("cookie", "bravo"),
422                         pair("cookie", "charlie"),
423                 },
424         })
425         if err != nil {
426                 t.Fatalf("Error st.http2() = %v", err)
427         }
428         if got, want := res.status, 200; got != want {
429                 t.Errorf("status: %v; want %v", got, want)
430         }
431 }
432
433 // TestH2H1TETrailers tests that server accepts TE request header
434 // field if it has trailers only.
435 func TestH2H1TETrailers(t *testing.T) {
436         st := newServerTester(nil, t, noopHandler)
437         defer st.Close()
438
439         res, err := st.http2(requestParam{
440                 name: "TestH2H1TETrailers",
441                 header: []hpack.HeaderField{
442                         pair("te", "trailers"),
443                 },
444         })
445         if err != nil {
446                 t.Fatalf("Error st.http2() = %v", err)
447         }
448         if got, want := res.status, 200; got != want {
449                 t.Errorf("status: %v; want %v", got, want)
450         }
451 }
452
453 // TestH2H1TEGzip tests that server resets stream if TE request header
454 // field contains gzip.
455 func TestH2H1TEGzip(t *testing.T) {
456         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
457                 t.Error("server should not forward bad request")
458         })
459         defer st.Close()
460
461         res, err := st.http2(requestParam{
462                 name: "TestH2H1TEGzip",
463                 header: []hpack.HeaderField{
464                         pair("te", "gzip"),
465                 },
466         })
467         if err != nil {
468                 t.Fatalf("Error st.http2() = %v", err)
469         }
470         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
471                 t.Errorf("res.errCode = %v; want %v", res.errCode, want)
472         }
473 }
474
475 // TestH2H1SNI tests server's TLS SNI extension feature.  It must
476 // choose appropriate certificate depending on the indicated
477 // server_name from client.
478 func TestH2H1SNI(t *testing.T) {
479         st := newServerTesterTLSConfig([]string{"--subcert=" + testDir + "/alt-server.key:" + testDir + "/alt-server.crt"}, t, noopHandler, &tls.Config{
480                 ServerName: "alt-domain",
481         })
482         defer st.Close()
483
484         tlsConn := st.conn.(*tls.Conn)
485         connState := tlsConn.ConnectionState()
486         cert := connState.PeerCertificates[0]
487
488         if got, want := cert.Subject.CommonName, "alt-domain"; got != want {
489                 t.Errorf("CommonName: %v; want %v", got, want)
490         }
491 }
492
493 // TestH2H1ServerPush tests server push using Link header field from
494 // backend server.
495 func TestH2H1ServerPush(t *testing.T) {
496         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
497                 // only resources marked as rel=preload are pushed
498                 if !strings.HasPrefix(r.URL.Path, "/css/") {
499                         w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
500                 }
501         })
502         defer st.Close()
503
504         res, err := st.http2(requestParam{
505                 name: "TestH2H1ServerPush",
506         })
507         if err != nil {
508                 t.Fatalf("Error st.http2() = %v", err)
509         }
510         if got, want := res.status, 200; got != want {
511                 t.Errorf("res.status: %v; want %v", got, want)
512         }
513         if got, want := len(res.pushResponse), 2; got != want {
514                 t.Fatalf("len(res.pushResponse): %v; want %v", got, want)
515         }
516         mainCSS := res.pushResponse[0]
517         if got, want := mainCSS.status, 200; got != want {
518                 t.Errorf("mainCSS.status: %v; want %v", got, want)
519         }
520         themeCSS := res.pushResponse[1]
521         if got, want := themeCSS.status, 200; got != want {
522                 t.Errorf("themeCSS.status: %v; want %v", got, want)
523         }
524 }
525
526 // TestH2H1RequestTrailer tests request trailer part is forwarded to
527 // backend.
528 func TestH2H1RequestTrailer(t *testing.T) {
529         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
530                 buf := make([]byte, 4096)
531                 for {
532                         _, err := r.Body.Read(buf)
533                         if err == io.EOF {
534                                 break
535                         }
536                         if err != nil {
537                                 t.Fatalf("r.Body.Read() = %v", err)
538                         }
539                 }
540                 if got, want := r.Trailer.Get("foo"), "bar"; got != want {
541                         t.Errorf("r.Trailer.Get(foo): %v; want %v", got, want)
542                 }
543         })
544         defer st.Close()
545
546         res, err := st.http2(requestParam{
547                 name: "TestH2H1RequestTrailer",
548                 body: []byte("1"),
549                 trailer: []hpack.HeaderField{
550                         pair("foo", "bar"),
551                 },
552         })
553         if err != nil {
554                 t.Fatalf("Error st.http2() = %v", err)
555         }
556         if got, want := res.status, 200; got != want {
557                 t.Errorf("res.status: %v; want %v", got, want)
558         }
559 }
560
561 // TestH2H1HeaderFieldBuffer tests that request with header fields
562 // larger than configured buffer size is rejected.
563 func TestH2H1HeaderFieldBuffer(t *testing.T) {
564         st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
565                 t.Fatal("execution path should not be here")
566         })
567         defer st.Close()
568
569         res, err := st.http2(requestParam{
570                 name: "TestH2H1HeaderFieldBuffer",
571         })
572         if err != nil {
573                 t.Fatalf("Error st.http2() = %v", err)
574         }
575         if got, want := res.status, 431; got != want {
576                 t.Errorf("status: %v; want %v", got, want)
577         }
578 }
579
580 // TestH2H1HeaderFields tests that request with header fields more
581 // than configured number is rejected.
582 func TestH2H1HeaderFields(t *testing.T) {
583         st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
584                 t.Fatal("execution path should not be here")
585         })
586         defer st.Close()
587
588         res, err := st.http2(requestParam{
589                 name: "TestH2H1HeaderFields",
590                 // we have at least 4 pseudo-header fields sent, and
591                 // that ensures that buffer limit exceeds.
592         })
593         if err != nil {
594                 t.Fatalf("Error st.http2() = %v", err)
595         }
596         if got, want := res.status, 431; got != want {
597                 t.Errorf("status: %v; want %v", got, want)
598         }
599 }
600
601 // TestH2H1Upgrade tests HTTP Upgrade to HTTP/2
602 func TestH2H1Upgrade(t *testing.T) {
603         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {})
604         defer st.Close()
605
606         res, err := st.http1(requestParam{
607                 name: "TestH2H1Upgrade",
608                 header: []hpack.HeaderField{
609                         pair("Connection", "Upgrade, HTTP2-Settings"),
610                         pair("Upgrade", "h2c"),
611                         pair("HTTP2-Settings", "AAMAAABkAAQAAP__"),
612                 },
613         })
614
615         if err != nil {
616                 t.Fatalf("Error st.http1() = %v", err)
617         }
618
619         if got, want := res.status, 101; got != want {
620                 t.Errorf("res.status: %v; want %v", got, want)
621         }
622
623         res, err = st.http2(requestParam{
624                 httpUpgrade: true,
625         })
626         if err != nil {
627                 t.Fatalf("Error st.http2() = %v", err)
628         }
629         if got, want := res.status, 200; got != want {
630                 t.Errorf("res.status: %v; want %v", got, want)
631         }
632 }
633
634 // TestH2H1GracefulShutdown tests graceful shutdown.
635 func TestH2H1GracefulShutdown(t *testing.T) {
636         st := newServerTester(nil, t, noopHandler)
637         defer st.Close()
638
639         fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
640         if err := st.fr.WriteSettings(); err != nil {
641                 t.Fatalf("st.fr.WriteSettings(): %v", err)
642         }
643
644         header := []hpack.HeaderField{
645                 pair(":method", "GET"),
646                 pair(":scheme", "http"),
647                 pair(":authority", st.authority),
648                 pair(":path", "/"),
649         }
650
651         for _, h := range header {
652                 _ = st.enc.WriteField(h)
653         }
654
655         if err := st.fr.WriteHeaders(http2.HeadersFrameParam{
656                 StreamID:      1,
657                 EndStream:     false,
658                 EndHeaders:    true,
659                 BlockFragment: st.headerBlkBuf.Bytes(),
660         }); err != nil {
661                 t.Fatalf("st.fr.WriteHeaders(): %v", err)
662         }
663
664         // send SIGQUIT signal to nghttpx to perform graceful shutdown
665         st.cmd.Process.Signal(syscall.SIGQUIT)
666
667         // after signal, finish request body
668         if err := st.fr.WriteData(1, true, nil); err != nil {
669                 t.Fatalf("st.fr.WriteData(): %v", err)
670         }
671
672         numGoAway := 0
673
674         for {
675                 fr, err := st.readFrame()
676                 if err != nil {
677                         if err == io.EOF {
678                                 want := 2
679                                 if got := numGoAway; got != want {
680                                         t.Fatalf("numGoAway: %v; want %v", got, want)
681                                 }
682                                 return
683                         }
684                         t.Fatalf("st.readFrame(): %v", err)
685                 }
686                 switch f := fr.(type) {
687                 case *http2.GoAwayFrame:
688                         numGoAway += 1
689                         want := http2.ErrCodeNo
690                         if got := f.ErrCode; got != want {
691                                 t.Fatalf("f.ErrCode(%v): %v; want %v", numGoAway, got, want)
692                         }
693                         switch numGoAway {
694                         case 1:
695                                 want := (uint32(1) << 31) - 1
696                                 if got := f.LastStreamID; got != want {
697                                         t.Fatalf("f.LastStreamID(%v): %v; want %v", numGoAway, got, want)
698                                 }
699                         case 2:
700                                 want := uint32(1)
701                                 if got := f.LastStreamID; got != want {
702                                         t.Fatalf("f.LastStreamID(%v): %v; want %v", numGoAway, got, want)
703                                 }
704                         case 3:
705                                 t.Fatalf("too many GOAWAYs received")
706                         }
707                 }
708         }
709 }
710
711 // TestH2H2MultipleResponseCL tests that server returns error if
712 // multiple Content-Length response header fields are received.
713 func TestH2H2MultipleResponseCL(t *testing.T) {
714         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
715                 w.Header().Add("content-length", "1")
716                 w.Header().Add("content-length", "1")
717         })
718         defer st.Close()
719
720         res, err := st.http2(requestParam{
721                 name: "TestH2H2MultipleResponseCL",
722         })
723         if err != nil {
724                 t.Fatalf("Error st.http2() = %v", err)
725         }
726         if got, want := res.errCode, http2.ErrCodeInternal; got != want {
727                 t.Errorf("res.errCode: %v; want %v", got, want)
728         }
729 }
730
731 // TestH2H2InvalidResponseCL tests that server returns error if
732 // Content-Length response header field value cannot be parsed as a
733 // number.
734 func TestH2H2InvalidResponseCL(t *testing.T) {
735         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
736                 w.Header().Add("content-length", "")
737         })
738         defer st.Close()
739
740         res, err := st.http2(requestParam{
741                 name: "TestH2H2InvalidResponseCL",
742         })
743         if err != nil {
744                 t.Fatalf("Error st.http2() = %v", err)
745         }
746         if got, want := res.errCode, http2.ErrCodeInternal; got != want {
747                 t.Errorf("res.errCode: %v; want %v", got, want)
748         }
749 }
750
751 // TestH2H2ConnectFailure tests that server handles the situation that
752 // connection attempt to HTTP/2 backend failed.
753 func TestH2H2ConnectFailure(t *testing.T) {
754         st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
755         defer st.Close()
756
757         // simulate backend connect attempt failure
758         st.ts.Close()
759
760         res, err := st.http2(requestParam{
761                 name: "TestH2H2ConnectFailure",
762         })
763         if err != nil {
764                 t.Fatalf("Error st.http2() = %v", err)
765         }
766         want := 503
767         if got := res.status; got != want {
768                 t.Errorf("status: %v; want %v", got, want)
769         }
770 }
771
772 // TestH2H2HostRewrite tests that server rewrites host header field
773 func TestH2H2HostRewrite(t *testing.T) {
774         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
775                 w.Header().Add("request-host", r.Host)
776         })
777         defer st.Close()
778
779         res, err := st.http2(requestParam{
780                 name: "TestH2H2HostRewrite",
781         })
782         if err != nil {
783                 t.Fatalf("Error st.http2() = %v", err)
784         }
785         if got, want := res.status, 200; got != want {
786                 t.Errorf("status: %v; want %v", got, want)
787         }
788         if got, want := res.header.Get("request-host"), st.backendHost; got != want {
789                 t.Errorf("request-host: %v; want %v", got, want)
790         }
791 }
792
793 // TestH2H2NoHostRewrite tests that server does not rewrite host
794 // header field
795 func TestH2H2NoHostRewrite(t *testing.T) {
796         st := newServerTester([]string{"--http2-bridge", "--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
797                 w.Header().Add("request-host", r.Host)
798         })
799         defer st.Close()
800
801         res, err := st.http2(requestParam{
802                 name: "TestH2H2NoHostRewrite",
803         })
804         if err != nil {
805                 t.Fatalf("Error st.http2() = %v", err)
806         }
807         if got, want := res.status, 200; got != want {
808                 t.Errorf("status: %v; want %v", got, want)
809         }
810         if got, want := res.header.Get("request-host"), st.frontendHost; got != want {
811                 t.Errorf("request-host: %v; want %v", got, want)
812         }
813 }