Apply PIE to nghttpx
[platform/upstream/nghttp2.git] / integration-tests / nghttpx_http2_test.go
1 package nghttp2
2
3 import (
4         "bytes"
5         "crypto/tls"
6         "encoding/json"
7         "fmt"
8         "golang.org/x/net/http2"
9         "golang.org/x/net/http2/hpack"
10         "io"
11         "io/ioutil"
12         "net"
13         "net/http"
14         "regexp"
15         "strings"
16         "syscall"
17         "testing"
18         "time"
19 )
20
21 // TestH2H1PlainGET tests whether simple HTTP/2 GET request works.
22 func TestH2H1PlainGET(t *testing.T) {
23         st := newServerTester(nil, t, noopHandler)
24         defer st.Close()
25
26         res, err := st.http2(requestParam{
27                 name: "TestH2H1PlainGET",
28         })
29         if err != nil {
30                 t.Fatalf("Error st.http2() = %v", err)
31         }
32
33         want := 200
34         if res.status != want {
35                 t.Errorf("status = %v; want %v", res.status, want)
36         }
37 }
38
39 // TestH2H1AddXfp tests that server appends :scheme to the existing
40 // x-forwarded-proto header field.
41 func TestH2H1AddXfp(t *testing.T) {
42         st := newServerTester([]string{"--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
43                 xfp := r.Header.Get("X-Forwarded-Proto")
44                 if got, want := xfp, "foo, http"; got != want {
45                         t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
46                 }
47         })
48         defer st.Close()
49
50         res, err := st.http2(requestParam{
51                 name: "TestH2H1AddXfp",
52                 header: []hpack.HeaderField{
53                         pair("x-forwarded-proto", "foo"),
54                 },
55         })
56         if err != nil {
57                 t.Fatalf("Error st.http2() = %v", err)
58         }
59         if got, want := res.status, 200; got != want {
60                 t.Errorf("status = %v; want %v", got, want)
61         }
62 }
63
64 // TestH2H1NoAddXfp tests that server does not append :scheme to the
65 // existing x-forwarded-proto header field.
66 func TestH2H1NoAddXfp(t *testing.T) {
67         st := newServerTester([]string{"--no-add-x-forwarded-proto", "--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
68                 xfp := r.Header.Get("X-Forwarded-Proto")
69                 if got, want := xfp, "foo"; got != want {
70                         t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
71                 }
72         })
73         defer st.Close()
74
75         res, err := st.http2(requestParam{
76                 name: "TestH2H1NoAddXfp",
77                 header: []hpack.HeaderField{
78                         pair("x-forwarded-proto", "foo"),
79                 },
80         })
81         if err != nil {
82                 t.Fatalf("Error st.http2() = %v", err)
83         }
84         if got, want := res.status, 200; got != want {
85                 t.Errorf("status = %v; want %v", got, want)
86         }
87 }
88
89 // TestH2H1StripXfp tests that server strips incoming
90 // x-forwarded-proto header field.
91 func TestH2H1StripXfp(t *testing.T) {
92         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
93                 xfp := r.Header.Get("X-Forwarded-Proto")
94                 if got, want := xfp, "http"; got != want {
95                         t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
96                 }
97         })
98         defer st.Close()
99
100         res, err := st.http2(requestParam{
101                 name: "TestH2H1StripXfp",
102                 header: []hpack.HeaderField{
103                         pair("x-forwarded-proto", "foo"),
104                 },
105         })
106         if err != nil {
107                 t.Fatalf("Error st.http2() = %v", err)
108         }
109         if got, want := res.status, 200; got != want {
110                 t.Errorf("status = %v; want %v", got, want)
111         }
112 }
113
114 // TestH2H1StripNoAddXfp tests that server strips incoming
115 // x-forwarded-proto header field, and does not add another.
116 func TestH2H1StripNoAddXfp(t *testing.T) {
117         st := newServerTester([]string{"--no-add-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
118                 if got, found := r.Header["X-Forwarded-Proto"]; found {
119                         t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
120                 }
121         })
122         defer st.Close()
123
124         res, err := st.http2(requestParam{
125                 name: "TestH2H1StripNoAddXfp",
126                 header: []hpack.HeaderField{
127                         pair("x-forwarded-proto", "foo"),
128                 },
129         })
130         if err != nil {
131                 t.Fatalf("Error st.http2() = %v", err)
132         }
133         if got, want := res.status, 200; got != want {
134                 t.Errorf("status = %v; want %v", got, want)
135         }
136 }
137
138 // TestH2H1AddXff tests that server generates X-Forwarded-For header
139 // field when forwarding request to backend.
140 func TestH2H1AddXff(t *testing.T) {
141         st := newServerTester([]string{"--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
142                 xff := r.Header.Get("X-Forwarded-For")
143                 want := "127.0.0.1"
144                 if xff != want {
145                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
146                 }
147         })
148         defer st.Close()
149
150         res, err := st.http2(requestParam{
151                 name: "TestH2H1AddXff",
152         })
153         if err != nil {
154                 t.Fatalf("Error st.http2() = %v", err)
155         }
156         if got, want := res.status, 200; got != want {
157                 t.Errorf("status = %v; want %v", got, want)
158         }
159 }
160
161 // TestH2H1AddXff2 tests that server appends X-Forwarded-For header
162 // field to existing one when forwarding request to backend.
163 func TestH2H1AddXff2(t *testing.T) {
164         st := newServerTester([]string{"--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
165                 xff := r.Header.Get("X-Forwarded-For")
166                 want := "host, 127.0.0.1"
167                 if xff != want {
168                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
169                 }
170         })
171         defer st.Close()
172
173         res, err := st.http2(requestParam{
174                 name: "TestH2H1AddXff2",
175                 header: []hpack.HeaderField{
176                         pair("x-forwarded-for", "host"),
177                 },
178         })
179         if err != nil {
180                 t.Fatalf("Error st.http2() = %v", err)
181         }
182         if got, want := res.status, 200; got != want {
183                 t.Errorf("status = %v; want %v", got, want)
184         }
185 }
186
187 // TestH2H1StripXff tests that --strip-incoming-x-forwarded-for
188 // option.
189 func TestH2H1StripXff(t *testing.T) {
190         st := newServerTester([]string{"--strip-incoming-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
191                 if xff, found := r.Header["X-Forwarded-For"]; found {
192                         t.Errorf("X-Forwarded-For = %v; want nothing", xff)
193                 }
194         })
195         defer st.Close()
196
197         res, err := st.http2(requestParam{
198                 name: "TestH2H1StripXff",
199                 header: []hpack.HeaderField{
200                         pair("x-forwarded-for", "host"),
201                 },
202         })
203         if err != nil {
204                 t.Fatalf("Error st.http2() = %v", err)
205         }
206         if got, want := res.status, 200; got != want {
207                 t.Errorf("status = %v; want %v", got, want)
208         }
209 }
210
211 // TestH2H1StripAddXff tests that --strip-incoming-x-forwarded-for and
212 // --add-x-forwarded-for options.
213 func TestH2H1StripAddXff(t *testing.T) {
214         args := []string{
215                 "--strip-incoming-x-forwarded-for",
216                 "--add-x-forwarded-for",
217         }
218         st := newServerTester(args, t, func(w http.ResponseWriter, r *http.Request) {
219                 xff := r.Header.Get("X-Forwarded-For")
220                 want := "127.0.0.1"
221                 if xff != want {
222                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
223                 }
224         })
225         defer st.Close()
226
227         res, err := st.http2(requestParam{
228                 name: "TestH2H1StripAddXff",
229                 header: []hpack.HeaderField{
230                         pair("x-forwarded-for", "host"),
231                 },
232         })
233         if err != nil {
234                 t.Fatalf("Error st.http2() = %v", err)
235         }
236         if got, want := res.status, 200; got != want {
237                 t.Errorf("status = %v; want %v", got, want)
238         }
239 }
240
241 // TestH2H1AddForwardedObfuscated tests that server generates
242 // Forwarded header field with obfuscated "by" and "for" parameters.
243 func TestH2H1AddForwardedObfuscated(t *testing.T) {
244         st := newServerTester([]string{"--add-forwarded=by,for,host,proto"}, t, func(w http.ResponseWriter, r *http.Request) {
245                 pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127\.0\.0\.1:%v";proto=http`, serverPort)
246                 validFwd := regexp.MustCompile(pattern)
247                 got := r.Header.Get("Forwarded")
248
249                 if !validFwd.MatchString(got) {
250                         t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
251                 }
252         })
253         defer st.Close()
254
255         res, err := st.http2(requestParam{
256                 name: "TestH2H1AddForwardedObfuscated",
257         })
258         if err != nil {
259                 t.Fatalf("Error st.http2() = %v", err)
260         }
261         if got, want := res.status, 200; got != want {
262                 t.Errorf("status: %v; want %v", got, want)
263         }
264 }
265
266 // TestH2H1AddForwardedByIP tests that server generates Forwarded header
267 // field with IP address in "by" parameter.
268 func TestH2H1AddForwardedByIP(t *testing.T) {
269         st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
270                 pattern := fmt.Sprintf(`by="127\.0\.0\.1:%v";for=_[^;]+`, serverPort)
271                 validFwd := regexp.MustCompile(pattern)
272                 if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
273                         t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
274                 }
275         })
276         defer st.Close()
277
278         res, err := st.http2(requestParam{
279                 name: "TestH2H1AddForwardedByIP",
280         })
281         if err != nil {
282                 t.Fatalf("Error st.http2() = %v", err)
283         }
284         if got, want := res.status, 200; got != want {
285                 t.Errorf("status: %v; want %v", got, want)
286         }
287 }
288
289 // TestH2H1AddForwardedForIP tests that server generates Forwarded header
290 // field with IP address in "for" parameters.
291 func TestH2H1AddForwardedForIP(t *testing.T) {
292         st := newServerTester([]string{"--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
293                 want := fmt.Sprintf(`by=_alpha;for=127.0.0.1;host="127.0.0.1:%v";proto=http`, serverPort)
294                 if got := r.Header.Get("Forwarded"); got != want {
295                         t.Errorf("Forwarded = %v; want %v", got, want)
296                 }
297         })
298         defer st.Close()
299
300         res, err := st.http2(requestParam{
301                 name: "TestH2H1AddForwardedForIP",
302         })
303         if err != nil {
304                 t.Fatalf("Error st.http2() = %v", err)
305         }
306         if got, want := res.status, 200; got != want {
307                 t.Errorf("status: %v; want %v", got, want)
308         }
309 }
310
311 // TestH2H1AddForwardedMerge tests that server generates Forwarded
312 // header field with IP address in "by" and "for" parameters.  The
313 // generated values must be appended to the existing value.
314 func TestH2H1AddForwardedMerge(t *testing.T) {
315         st := newServerTester([]string{"--add-forwarded=proto"}, t, func(w http.ResponseWriter, r *http.Request) {
316                 if got, want := r.Header.Get("Forwarded"), `host=foo, proto=http`; got != want {
317                         t.Errorf("Forwarded = %v; want %v", got, want)
318                 }
319         })
320         defer st.Close()
321
322         res, err := st.http2(requestParam{
323                 name: "TestH2H1AddForwardedMerge",
324                 header: []hpack.HeaderField{
325                         pair("forwarded", "host=foo"),
326                 },
327         })
328         if err != nil {
329                 t.Fatalf("Error st.http2() = %v", err)
330         }
331         if got, want := res.status, 200; got != want {
332                 t.Errorf("status: %v; want %v", got, want)
333         }
334 }
335
336 // TestH2H1AddForwardedStrip tests that server generates Forwarded
337 // header field with IP address in "by" and "for" parameters.  The
338 // generated values must not include the existing value.
339 func TestH2H1AddForwardedStrip(t *testing.T) {
340         st := newServerTester([]string{"--strip-incoming-forwarded", "--add-forwarded=proto"}, t, func(w http.ResponseWriter, r *http.Request) {
341                 if got, want := r.Header.Get("Forwarded"), `proto=http`; got != want {
342                         t.Errorf("Forwarded = %v; want %v", got, want)
343                 }
344         })
345         defer st.Close()
346
347         res, err := st.http2(requestParam{
348                 name: "TestH2H1AddForwardedStrip",
349                 header: []hpack.HeaderField{
350                         pair("forwarded", "host=foo"),
351                 },
352         })
353         if err != nil {
354                 t.Fatalf("Error st.http2() = %v", err)
355         }
356         if got, want := res.status, 200; got != want {
357                 t.Errorf("status: %v; want %v", got, want)
358         }
359 }
360
361 // TestH2H1StripForwarded tests that server strips incoming Forwarded
362 // header field.
363 func TestH2H1StripForwarded(t *testing.T) {
364         st := newServerTester([]string{"--strip-incoming-forwarded"}, t, func(w http.ResponseWriter, r *http.Request) {
365                 if got, found := r.Header["Forwarded"]; found {
366                         t.Errorf("Forwarded = %v; want nothing", got)
367                 }
368         })
369         defer st.Close()
370
371         res, err := st.http2(requestParam{
372                 name: "TestH2H1StripForwarded",
373                 header: []hpack.HeaderField{
374                         pair("forwarded", "host=foo"),
375                 },
376         })
377         if err != nil {
378                 t.Fatalf("Error st.http2() = %v", err)
379         }
380         if got, want := res.status, 200; got != want {
381                 t.Errorf("status: %v; want %v", got, want)
382         }
383 }
384
385 // TestH2H1AddForwardedStatic tests that server generates Forwarded
386 // header field with the given static obfuscated string for "by"
387 // parameter.
388 func TestH2H1AddForwardedStatic(t *testing.T) {
389         st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
390                 pattern := `by=_alpha;for=_[^;]+`
391                 validFwd := regexp.MustCompile(pattern)
392                 if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
393                         t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
394                 }
395         })
396         defer st.Close()
397
398         res, err := st.http2(requestParam{
399                 name: "TestH2H1AddForwardedStatic",
400         })
401         if err != nil {
402                 t.Fatalf("Error st.http2() = %v", err)
403         }
404         if got, want := res.status, 200; got != want {
405                 t.Errorf("status: %v; want %v", got, want)
406         }
407 }
408
409 // TestH2H1GenerateVia tests that server generates Via header field to and
410 // from backend server.
411 func TestH2H1GenerateVia(t *testing.T) {
412         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
413                 if got, want := r.Header.Get("Via"), "2 nghttpx"; got != want {
414                         t.Errorf("Via: %v; want %v", got, want)
415                 }
416         })
417         defer st.Close()
418
419         res, err := st.http2(requestParam{
420                 name: "TestH2H1GenerateVia",
421         })
422         if err != nil {
423                 t.Fatalf("Error st.http2() = %v", err)
424         }
425         if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
426                 t.Errorf("Via: %v; want %v", got, want)
427         }
428 }
429
430 // TestH2H1AppendVia tests that server adds value to existing Via
431 // header field to and from backend server.
432 func TestH2H1AppendVia(t *testing.T) {
433         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
434                 if got, want := r.Header.Get("Via"), "foo, 2 nghttpx"; got != want {
435                         t.Errorf("Via: %v; want %v", got, want)
436                 }
437                 w.Header().Add("Via", "bar")
438         })
439         defer st.Close()
440
441         res, err := st.http2(requestParam{
442                 name: "TestH2H1AppendVia",
443                 header: []hpack.HeaderField{
444                         pair("via", "foo"),
445                 },
446         })
447         if err != nil {
448                 t.Fatalf("Error st.http2() = %v", err)
449         }
450         if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
451                 t.Errorf("Via: %v; want %v", got, want)
452         }
453 }
454
455 // TestH2H1NoVia tests that server does not add value to existing Via
456 // header field to and from backend server.
457 func TestH2H1NoVia(t *testing.T) {
458         st := newServerTester([]string{"--no-via"}, t, func(w http.ResponseWriter, r *http.Request) {
459                 if got, want := r.Header.Get("Via"), "foo"; got != want {
460                         t.Errorf("Via: %v; want %v", got, want)
461                 }
462                 w.Header().Add("Via", "bar")
463         })
464         defer st.Close()
465
466         res, err := st.http2(requestParam{
467                 name: "TestH2H1NoVia",
468                 header: []hpack.HeaderField{
469                         pair("via", "foo"),
470                 },
471         })
472         if err != nil {
473                 t.Fatalf("Error st.http2() = %v", err)
474         }
475         if got, want := res.header.Get("Via"), "bar"; got != want {
476                 t.Errorf("Via: %v; want %v", got, want)
477         }
478 }
479
480 // TestH2H1HostRewrite tests that server rewrites host header field
481 func TestH2H1HostRewrite(t *testing.T) {
482         st := newServerTester([]string{"--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
483                 w.Header().Add("request-host", r.Host)
484         })
485         defer st.Close()
486
487         res, err := st.http2(requestParam{
488                 name: "TestH2H1HostRewrite",
489         })
490         if err != nil {
491                 t.Fatalf("Error st.http2() = %v", err)
492         }
493         if got, want := res.status, 200; got != want {
494                 t.Errorf("status: %v; want %v", got, want)
495         }
496         if got, want := res.header.Get("request-host"), st.backendHost; got != want {
497                 t.Errorf("request-host: %v; want %v", got, want)
498         }
499 }
500
501 // TestH2H1NoHostRewrite tests that server does not rewrite host
502 // header field
503 func TestH2H1NoHostRewrite(t *testing.T) {
504         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
505                 w.Header().Add("request-host", r.Host)
506         })
507         defer st.Close()
508
509         res, err := st.http2(requestParam{
510                 name: "TestH2H1NoHostRewrite",
511         })
512         if err != nil {
513                 t.Fatalf("Error st.http2() = %v", err)
514         }
515         if got, want := res.status, 200; got != want {
516                 t.Errorf("status: %v; want %v", got, want)
517         }
518         if got, want := res.header.Get("request-host"), st.frontendHost; got != want {
519                 t.Errorf("request-host: %v; want %v", got, want)
520         }
521 }
522
523 // TestH2H1BadRequestCL tests that server rejects request whose
524 // content-length header field value does not match its request body
525 // size.
526 func TestH2H1BadRequestCL(t *testing.T) {
527         st := newServerTester(nil, t, noopHandler)
528         defer st.Close()
529
530         // we set content-length: 1024, but the actual request body is
531         // 3 bytes.
532         res, err := st.http2(requestParam{
533                 name:   "TestH2H1BadRequestCL",
534                 method: "POST",
535                 header: []hpack.HeaderField{
536                         pair("content-length", "1024"),
537                 },
538                 body: []byte("foo"),
539         })
540         if err != nil {
541                 t.Fatalf("Error st.http2() = %v", err)
542         }
543
544         want := http2.ErrCodeProtocol
545         if res.errCode != want {
546                 t.Errorf("res.errCode = %v; want %v", res.errCode, want)
547         }
548 }
549
550 // TestH2H1BadResponseCL tests that server returns error when
551 // content-length response header field value does not match its
552 // response body size.
553 func TestH2H1BadResponseCL(t *testing.T) {
554         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
555                 // we set content-length: 1024, but only send 3 bytes.
556                 w.Header().Add("Content-Length", "1024")
557                 w.Write([]byte("foo"))
558         })
559         defer st.Close()
560
561         res, err := st.http2(requestParam{
562                 name: "TestH2H1BadResponseCL",
563         })
564         if err != nil {
565                 t.Fatalf("Error st.http2() = %v", err)
566         }
567
568         want := http2.ErrCodeProtocol
569         if res.errCode != want {
570                 t.Errorf("res.errCode = %v; want %v", res.errCode, want)
571         }
572 }
573
574 // TestH2H1LocationRewrite tests location header field rewriting
575 // works.
576 func TestH2H1LocationRewrite(t *testing.T) {
577         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
578                 // TODO we cannot get st.ts's port number here.. 8443
579                 // is just a place holder.  We ignore it on rewrite.
580                 w.Header().Add("Location", "http://127.0.0.1:8443/p/q?a=b#fragment")
581         })
582         defer st.Close()
583
584         res, err := st.http2(requestParam{
585                 name: "TestH2H1LocationRewrite",
586         })
587         if err != nil {
588                 t.Fatalf("Error st.http2() = %v", err)
589         }
590
591         want := fmt.Sprintf("http://127.0.0.1:%v/p/q?a=b#fragment", serverPort)
592         if got := res.header.Get("Location"); got != want {
593                 t.Errorf("Location: %v; want %v", got, want)
594         }
595 }
596
597 // TestH2H1ChunkedRequestBody tests that chunked request body works.
598 func TestH2H1ChunkedRequestBody(t *testing.T) {
599         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
600                 want := "[chunked]"
601                 if got := fmt.Sprint(r.TransferEncoding); got != want {
602                         t.Errorf("Transfer-Encoding: %v; want %v", got, want)
603                 }
604                 body, err := ioutil.ReadAll(r.Body)
605                 if err != nil {
606                         t.Fatalf("Error reading r.body: %v", err)
607                 }
608                 want = "foo"
609                 if got := string(body); got != want {
610                         t.Errorf("body: %v; want %v", got, want)
611                 }
612         })
613         defer st.Close()
614
615         res, err := st.http2(requestParam{
616                 name:   "TestH2H1ChunkedRequestBody",
617                 method: "POST",
618                 body:   []byte("foo"),
619         })
620         if err != nil {
621                 t.Fatalf("Error st.http2() = %v", err)
622         }
623         if got, want := res.status, 200; got != want {
624                 t.Errorf("status = %v; want %v", got, want)
625         }
626 }
627
628 // TestH2H1MultipleRequestCL tests that server rejects request with
629 // multiple Content-Length request header fields.
630 func TestH2H1MultipleRequestCL(t *testing.T) {
631         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
632                 t.Errorf("server should not forward bad request")
633         })
634         defer st.Close()
635
636         res, err := st.http2(requestParam{
637                 name: "TestH2H1MultipleRequestCL",
638                 header: []hpack.HeaderField{
639                         pair("content-length", "1"),
640                         pair("content-length", "1"),
641                 },
642         })
643         if err != nil {
644                 t.Fatalf("Error st.http2() = %v", err)
645         }
646         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
647                 t.Errorf("res.errCode: %v; want %v", got, want)
648         }
649 }
650
651 // TestH2H1InvalidRequestCL tests that server rejects request with
652 // Content-Length which cannot be parsed as a number.
653 func TestH2H1InvalidRequestCL(t *testing.T) {
654         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
655                 t.Errorf("server should not forward bad request")
656         })
657         defer st.Close()
658
659         res, err := st.http2(requestParam{
660                 name: "TestH2H1InvalidRequestCL",
661                 header: []hpack.HeaderField{
662                         pair("content-length", ""),
663                 },
664         })
665         if err != nil {
666                 t.Fatalf("Error st.http2() = %v", err)
667         }
668         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
669                 t.Errorf("res.errCode: %v; want %v", got, want)
670         }
671 }
672
673 // // TestH2H1ConnectFailure tests that server handles the situation that
674 // // connection attempt to HTTP/1 backend failed.
675 // func TestH2H1ConnectFailure(t *testing.T) {
676 //      st := newServerTester(nil, t, noopHandler)
677 //      defer st.Close()
678
679 //      // shutdown backend server to simulate backend connect failure
680 //      st.ts.Close()
681
682 //      res, err := st.http2(requestParam{
683 //              name: "TestH2H1ConnectFailure",
684 //      })
685 //      if err != nil {
686 //              t.Fatalf("Error st.http2() = %v", err)
687 //      }
688 //      want := 503
689 //      if got := res.status; got != want {
690 //              t.Errorf("status: %v; want %v", got, want)
691 //      }
692 // }
693
694 // TestH2H1InvalidMethod tests that server rejects invalid method with
695 // 501.
696 func TestH2H1InvalidMethod(t *testing.T) {
697         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
698                 t.Errorf("server should not forward this request")
699         })
700         defer st.Close()
701
702         res, err := st.http2(requestParam{
703                 name:   "TestH2H1InvalidMethod",
704                 method: "get",
705         })
706         if err != nil {
707                 t.Fatalf("Error st.http2() = %v", err)
708         }
709         if got, want := res.status, 501; got != want {
710                 t.Errorf("status: %v; want %v", got, want)
711         }
712 }
713
714 // TestH2H1BadAuthority tests that server rejects request including
715 // bad characters in :authority header field.
716 func TestH2H1BadAuthority(t *testing.T) {
717         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
718                 t.Errorf("server should not forward this request")
719         })
720         defer st.Close()
721
722         res, err := st.http2(requestParam{
723                 name:      "TestH2H1BadAuthority",
724                 authority: `foo\bar`,
725         })
726         if err != nil {
727                 t.Fatalf("Error st.http2() = %v", err)
728         }
729         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
730                 t.Errorf("res.errCode: %v; want %v", got, want)
731         }
732 }
733
734 // TestH2H1BadScheme tests that server rejects request including
735 // bad characters in :scheme header field.
736 func TestH2H1BadScheme(t *testing.T) {
737         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
738                 t.Errorf("server should not forward this request")
739         })
740         defer st.Close()
741
742         res, err := st.http2(requestParam{
743                 name:   "TestH2H1BadScheme",
744                 scheme: "http*",
745         })
746         if err != nil {
747                 t.Fatalf("Error st.http2() = %v", err)
748         }
749         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
750                 t.Errorf("res.errCode: %v; want %v", got, want)
751         }
752 }
753
754 // TestH2H1AssembleCookies tests that crumbled cookies in HTTP/2
755 // request is assembled into 1 when forwarding to HTTP/1 backend link.
756 func TestH2H1AssembleCookies(t *testing.T) {
757         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
758                 if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
759                         t.Errorf("Cookie: %v; want %v", got, want)
760                 }
761         })
762         defer st.Close()
763
764         res, err := st.http2(requestParam{
765                 name: "TestH2H1AssembleCookies",
766                 header: []hpack.HeaderField{
767                         pair("cookie", "alpha"),
768                         pair("cookie", "bravo"),
769                         pair("cookie", "charlie"),
770                 },
771         })
772         if err != nil {
773                 t.Fatalf("Error st.http2() = %v", err)
774         }
775         if got, want := res.status, 200; got != want {
776                 t.Errorf("status: %v; want %v", got, want)
777         }
778 }
779
780 // TestH2H1TETrailers tests that server accepts TE request header
781 // field if it has trailers only.
782 func TestH2H1TETrailers(t *testing.T) {
783         st := newServerTester(nil, t, noopHandler)
784         defer st.Close()
785
786         res, err := st.http2(requestParam{
787                 name: "TestH2H1TETrailers",
788                 header: []hpack.HeaderField{
789                         pair("te", "trailers"),
790                 },
791         })
792         if err != nil {
793                 t.Fatalf("Error st.http2() = %v", err)
794         }
795         if got, want := res.status, 200; got != want {
796                 t.Errorf("status: %v; want %v", got, want)
797         }
798 }
799
800 // TestH2H1TEGzip tests that server resets stream if TE request header
801 // field contains gzip.
802 func TestH2H1TEGzip(t *testing.T) {
803         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
804                 t.Error("server should not forward bad request")
805         })
806         defer st.Close()
807
808         res, err := st.http2(requestParam{
809                 name: "TestH2H1TEGzip",
810                 header: []hpack.HeaderField{
811                         pair("te", "gzip"),
812                 },
813         })
814         if err != nil {
815                 t.Fatalf("Error st.http2() = %v", err)
816         }
817         if got, want := res.errCode, http2.ErrCodeProtocol; got != want {
818                 t.Errorf("res.errCode = %v; want %v", res.errCode, want)
819         }
820 }
821
822 // TestH2H1SNI tests server's TLS SNI extension feature.  It must
823 // choose appropriate certificate depending on the indicated
824 // server_name from client.
825 func TestH2H1SNI(t *testing.T) {
826         st := newServerTesterTLSConfig([]string{"--subcert=" + testDir + "/alt-server.key:" + testDir + "/alt-server.crt"}, t, noopHandler, &tls.Config{
827                 ServerName: "alt-domain",
828         })
829         defer st.Close()
830
831         tlsConn := st.conn.(*tls.Conn)
832         connState := tlsConn.ConnectionState()
833         cert := connState.PeerCertificates[0]
834
835         if got, want := cert.Subject.CommonName, "alt-domain"; got != want {
836                 t.Errorf("CommonName: %v; want %v", got, want)
837         }
838 }
839
840 // TestH2H1TLSXfp tests nghttpx sends x-forwarded-proto header field
841 // with http value since :scheme is http, even if the frontend
842 // connection is encrypted.
843 func TestH2H1TLSXfp(t *testing.T) {
844         st := newServerTesterTLS(nil, t, func(w http.ResponseWriter, r *http.Request) {
845                 if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
846                         t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
847                 }
848         })
849         defer st.Close()
850
851         res, err := st.http2(requestParam{
852                 name: "TestH2H1TLSXfp",
853         })
854         if err != nil {
855                 t.Fatalf("Error st.http2() = %v", err)
856         }
857         if got, want := res.status, 200; got != want {
858                 t.Errorf("res.status: %v; want %v", got, want)
859         }
860 }
861
862 // TestH2H1ServerPush tests server push using Link header field from
863 // backend server.
864 func TestH2H1ServerPush(t *testing.T) {
865         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
866                 // only resources marked as rel=preload are pushed
867                 if !strings.HasPrefix(r.URL.Path, "/css/") {
868                         w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
869                 }
870         })
871         defer st.Close()
872
873         res, err := st.http2(requestParam{
874                 name: "TestH2H1ServerPush",
875         })
876         if err != nil {
877                 t.Fatalf("Error st.http2() = %v", err)
878         }
879         if got, want := res.status, 200; got != want {
880                 t.Errorf("res.status: %v; want %v", got, want)
881         }
882         if got, want := len(res.pushResponse), 2; got != want {
883                 t.Fatalf("len(res.pushResponse): %v; want %v", got, want)
884         }
885         mainCSS := res.pushResponse[0]
886         if got, want := mainCSS.status, 200; got != want {
887                 t.Errorf("mainCSS.status: %v; want %v", got, want)
888         }
889         themeCSS := res.pushResponse[1]
890         if got, want := themeCSS.status, 200; got != want {
891                 t.Errorf("themeCSS.status: %v; want %v", got, want)
892         }
893 }
894
895 // TestH2H1RequestTrailer tests request trailer part is forwarded to
896 // backend.
897 func TestH2H1RequestTrailer(t *testing.T) {
898         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
899                 buf := make([]byte, 4096)
900                 for {
901                         _, err := r.Body.Read(buf)
902                         if err == io.EOF {
903                                 break
904                         }
905                         if err != nil {
906                                 t.Fatalf("r.Body.Read() = %v", err)
907                         }
908                 }
909                 if got, want := r.Trailer.Get("foo"), "bar"; got != want {
910                         t.Errorf("r.Trailer.Get(foo): %v; want %v", got, want)
911                 }
912         })
913         defer st.Close()
914
915         res, err := st.http2(requestParam{
916                 name: "TestH2H1RequestTrailer",
917                 body: []byte("1"),
918                 trailer: []hpack.HeaderField{
919                         pair("foo", "bar"),
920                 },
921         })
922         if err != nil {
923                 t.Fatalf("Error st.http2() = %v", err)
924         }
925         if got, want := res.status, 200; got != want {
926                 t.Errorf("res.status: %v; want %v", got, want)
927         }
928 }
929
930 // TestH2H1HeaderFieldBuffer tests that request with header fields
931 // larger than configured buffer size is rejected.
932 func TestH2H1HeaderFieldBuffer(t *testing.T) {
933         st := newServerTester([]string{"--request-header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
934                 t.Fatal("execution path should not be here")
935         })
936         defer st.Close()
937
938         res, err := st.http2(requestParam{
939                 name: "TestH2H1HeaderFieldBuffer",
940         })
941         if err != nil {
942                 t.Fatalf("Error st.http2() = %v", err)
943         }
944         if got, want := res.status, 431; got != want {
945                 t.Errorf("status: %v; want %v", got, want)
946         }
947 }
948
949 // TestH2H1HeaderFields tests that request with header fields more
950 // than configured number is rejected.
951 func TestH2H1HeaderFields(t *testing.T) {
952         st := newServerTester([]string{"--max-request-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
953                 t.Fatal("execution path should not be here")
954         })
955         defer st.Close()
956
957         res, err := st.http2(requestParam{
958                 name: "TestH2H1HeaderFields",
959                 // we have at least 4 pseudo-header fields sent, and
960                 // that ensures that buffer limit exceeds.
961         })
962         if err != nil {
963                 t.Fatalf("Error st.http2() = %v", err)
964         }
965         if got, want := res.status, 431; got != want {
966                 t.Errorf("status: %v; want %v", got, want)
967         }
968 }
969
970 // TestH2H1ReqPhaseSetHeader tests mruby request phase hook
971 // modifies request header fields.
972 func TestH2H1ReqPhaseSetHeader(t *testing.T) {
973         st := newServerTester([]string{"--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
974                 if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
975                         t.Errorf("User-Agent = %v; want %v", got, want)
976                 }
977         })
978         defer st.Close()
979
980         res, err := st.http2(requestParam{
981                 name: "TestH2H1ReqPhaseSetHeader",
982         })
983         if err != nil {
984                 t.Fatalf("Error st.http2() = %v", err)
985         }
986
987         if got, want := res.status, 200; got != want {
988                 t.Errorf("status = %v; want %v", got, want)
989         }
990 }
991
992 // TestH2H1ReqPhaseReturn tests mruby request phase hook returns
993 // custom response.
994 func TestH2H1ReqPhaseReturn(t *testing.T) {
995         st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
996                 t.Fatalf("request should not be forwarded")
997         })
998         defer st.Close()
999
1000         res, err := st.http2(requestParam{
1001                 name: "TestH2H1ReqPhaseReturn",
1002         })
1003         if err != nil {
1004                 t.Fatalf("Error st.http2() = %v", err)
1005         }
1006
1007         if got, want := res.status, 404; got != want {
1008                 t.Errorf("status = %v; want %v", got, want)
1009         }
1010
1011         hdtests := []struct {
1012                 k, v string
1013         }{
1014                 {"content-length", "20"},
1015                 {"from", "mruby"},
1016         }
1017         for _, tt := range hdtests {
1018                 if got, want := res.header.Get(tt.k), tt.v; got != want {
1019                         t.Errorf("%v = %v; want %v", tt.k, got, want)
1020                 }
1021         }
1022
1023         if got, want := string(res.body), "Hello World from req"; got != want {
1024                 t.Errorf("body = %v; want %v", got, want)
1025         }
1026 }
1027
1028 // TestH2H1RespPhaseSetHeader tests mruby response phase hook modifies
1029 // response header fields.
1030 func TestH2H1RespPhaseSetHeader(t *testing.T) {
1031         st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
1032         defer st.Close()
1033
1034         res, err := st.http2(requestParam{
1035                 name: "TestH2H1RespPhaseSetHeader",
1036         })
1037         if err != nil {
1038                 t.Fatalf("Error st.http2() = %v", err)
1039         }
1040
1041         if got, want := res.status, 200; got != want {
1042                 t.Errorf("status = %v; want %v", got, want)
1043         }
1044
1045         if got, want := res.header.Get("alpha"), "bravo"; got != want {
1046                 t.Errorf("alpha = %v; want %v", got, want)
1047         }
1048 }
1049
1050 // TestH2H1RespPhaseReturn tests mruby response phase hook returns
1051 // custom response.
1052 func TestH2H1RespPhaseReturn(t *testing.T) {
1053         st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
1054         defer st.Close()
1055
1056         res, err := st.http2(requestParam{
1057                 name: "TestH2H1RespPhaseReturn",
1058         })
1059         if err != nil {
1060                 t.Fatalf("Error st.http2() = %v", err)
1061         }
1062
1063         if got, want := res.status, 404; got != want {
1064                 t.Errorf("status = %v; want %v", got, want)
1065         }
1066
1067         hdtests := []struct {
1068                 k, v string
1069         }{
1070                 {"content-length", "21"},
1071                 {"from", "mruby"},
1072         }
1073         for _, tt := range hdtests {
1074                 if got, want := res.header.Get(tt.k), tt.v; got != want {
1075                         t.Errorf("%v = %v; want %v", tt.k, got, want)
1076                 }
1077         }
1078
1079         if got, want := string(res.body), "Hello World from resp"; got != want {
1080                 t.Errorf("body = %v; want %v", got, want)
1081         }
1082 }
1083
1084 // TestH2H1Upgrade tests HTTP Upgrade to HTTP/2
1085 func TestH2H1Upgrade(t *testing.T) {
1086         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {})
1087         defer st.Close()
1088
1089         res, err := st.http1(requestParam{
1090                 name: "TestH2H1Upgrade",
1091                 header: []hpack.HeaderField{
1092                         pair("Connection", "Upgrade, HTTP2-Settings"),
1093                         pair("Upgrade", "h2c"),
1094                         pair("HTTP2-Settings", "AAMAAABkAAQAAP__"),
1095                 },
1096         })
1097
1098         if err != nil {
1099                 t.Fatalf("Error st.http1() = %v", err)
1100         }
1101
1102         if got, want := res.status, 101; got != want {
1103                 t.Errorf("res.status: %v; want %v", got, want)
1104         }
1105
1106         res, err = st.http2(requestParam{
1107                 httpUpgrade: true,
1108         })
1109         if err != nil {
1110                 t.Fatalf("Error st.http2() = %v", err)
1111         }
1112         if got, want := res.status, 200; got != want {
1113                 t.Errorf("res.status: %v; want %v", got, want)
1114         }
1115 }
1116
1117 // TestH2H1ProxyProtocolV1ForwardedForObfuscated tests that Forwarded
1118 // header field includes obfuscated address even if PROXY protocol
1119 // version 1 containing TCP4 entry is accepted.
1120 func TestH2H1ProxyProtocolV1ForwardedForObfuscated(t *testing.T) {
1121         pattern := fmt.Sprintf(`^for=_[^;]+$`)
1122         validFwd := regexp.MustCompile(pattern)
1123         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=obfuscated"}, t, func(w http.ResponseWriter, r *http.Request) {
1124                 if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
1125                         t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
1126                 }
1127         })
1128         defer st.Close()
1129
1130         st.conn.Write([]byte("PROXY TCP4 192.168.0.2 192.168.0.100 12345 8080\r\n"))
1131
1132         res, err := st.http2(requestParam{
1133                 name: "TestH2H1ProxyProtocolV1ForwardedForObfuscated",
1134         })
1135
1136         if err != nil {
1137                 t.Fatalf("Error st.http2() = %v", err)
1138         }
1139
1140         if got, want := res.status, 200; got != want {
1141                 t.Errorf("res.status: %v; want %v", got, want)
1142         }
1143 }
1144
1145 // TestH2H1ProxyProtocolV1TCP4 tests PROXY protocol version 1
1146 // containing TCP4 entry is accepted and X-Forwarded-For contains
1147 // advertised src address.
1148 func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
1149         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1150                 if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
1151                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1152                 }
1153                 if got, want := r.Header.Get("Forwarded"), "for=192.168.0.2"; got != want {
1154                         t.Errorf("Forwarded: %v; want %v", got, want)
1155                 }
1156         })
1157         defer st.Close()
1158
1159         st.conn.Write([]byte("PROXY TCP4 192.168.0.2 192.168.0.100 12345 8080\r\n"))
1160
1161         res, err := st.http2(requestParam{
1162                 name: "TestH2H1ProxyProtocolV1TCP4",
1163         })
1164
1165         if err != nil {
1166                 t.Fatalf("Error st.http2() = %v", err)
1167         }
1168
1169         if got, want := res.status, 200; got != want {
1170                 t.Errorf("res.status: %v; want %v", got, want)
1171         }
1172 }
1173
1174 // TestH2H1ProxyProtocolV1TCP6 tests PROXY protocol version 1
1175 // containing TCP6 entry is accepted and X-Forwarded-For contains
1176 // advertised src address.
1177 func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
1178         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1179                 if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
1180                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1181                 }
1182                 if got, want := r.Header.Get("Forwarded"), `for="[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"`; got != want {
1183                         t.Errorf("Forwarded: %v; want %v", got, want)
1184                 }
1185         })
1186         defer st.Close()
1187
1188         st.conn.Write([]byte("PROXY TCP6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 ::1 12345 8080\r\n"))
1189
1190         res, err := st.http2(requestParam{
1191                 name: "TestH2H1ProxyProtocolV1TCP6",
1192         })
1193
1194         if err != nil {
1195                 t.Fatalf("Error st.http2() = %v", err)
1196         }
1197
1198         if got, want := res.status, 200; got != want {
1199                 t.Errorf("res.status: %v; want %v", got, want)
1200         }
1201 }
1202
1203 // TestH2H1ProxyProtocolV1Unknown tests PROXY protocol version 1
1204 // containing UNKNOWN entry is accepted.
1205 func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
1206         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1207                 if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
1208                         t.Errorf("X-Forwarded-For: %v; want something else", got)
1209                 }
1210                 if got, notWant := r.Header.Get("Forwarded"), "for=192.168.0.2"; got == notWant {
1211                         t.Errorf("Forwarded: %v; want something else", got)
1212                 }
1213         })
1214         defer st.Close()
1215
1216         st.conn.Write([]byte("PROXY UNKNOWN 192.168.0.2 192.168.0.100 12345 8080\r\n"))
1217
1218         res, err := st.http2(requestParam{
1219                 name: "TestH2H1ProxyProtocolV1Unknown",
1220         })
1221
1222         if err != nil {
1223                 t.Fatalf("Error st.http2() = %v", err)
1224         }
1225
1226         if got, want := res.status, 200; got != want {
1227                 t.Errorf("res.status: %v; want %v", got, want)
1228         }
1229 }
1230
1231 // TestH2H1ProxyProtocolV1JustUnknown tests PROXY protocol version 1
1232 // containing only "PROXY UNKNOWN" is accepted.
1233 func TestH2H1ProxyProtocolV1JustUnknown(t *testing.T) {
1234         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, noopHandler)
1235         defer st.Close()
1236
1237         st.conn.Write([]byte("PROXY UNKNOWN\r\n"))
1238
1239         res, err := st.http2(requestParam{
1240                 name: "TestH2H1ProxyProtocolV1JustUnknown",
1241         })
1242
1243         if err != nil {
1244                 t.Fatalf("Error st.http2() = %v", err)
1245         }
1246
1247         if got, want := res.status, 200; got != want {
1248                 t.Errorf("res.status: %v; want %v", got, want)
1249         }
1250 }
1251
1252 // TestH2H1ProxyProtocolV1TooLongLine tests PROXY protocol version 1
1253 // line longer than 107 bytes must be rejected
1254 func TestH2H1ProxyProtocolV1TooLongLine(t *testing.T) {
1255         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, noopHandler)
1256         defer st.Close()
1257
1258         st.conn.Write([]byte("PROXY UNKNOWN ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 655350\r\n"))
1259
1260         _, err := st.http2(requestParam{
1261                 name: "TestH2H1ProxyProtocolV1TooLongLine",
1262         })
1263
1264         if err == nil {
1265                 t.Fatalf("connection was not terminated")
1266         }
1267 }
1268
1269 // TestH2H1ProxyProtocolV1BadLineEnd tests that PROXY protocol version
1270 // 1 line ending without \r\n should be rejected.
1271 func TestH2H1ProxyProtocolV1BadLineEnd(t *testing.T) {
1272         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1273         defer st.Close()
1274
1275         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 8080\r \n"))
1276
1277         _, err := st.http2(requestParam{
1278                 name: "TestH2H1ProxyProtocolV1BadLineEnd",
1279         })
1280
1281         if err == nil {
1282                 t.Fatalf("connection was not terminated")
1283         }
1284 }
1285
1286 // TestH2H1ProxyProtocolV1NoEnd tests that PROXY protocol version 1
1287 // line containing no \r\n should be rejected.
1288 func TestH2H1ProxyProtocolV1NoEnd(t *testing.T) {
1289         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1290         defer st.Close()
1291
1292         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 8080"))
1293
1294         _, err := st.http2(requestParam{
1295                 name: "TestH2H1ProxyProtocolV1NoEnd",
1296         })
1297
1298         if err == nil {
1299                 t.Fatalf("connection was not terminated")
1300         }
1301 }
1302
1303 // TestH2H1ProxyProtocolV1EmbeddedNULL tests that PROXY protocol
1304 // version 1 line containing NULL character should be rejected.
1305 func TestH2H1ProxyProtocolV1EmbeddedNULL(t *testing.T) {
1306         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1307         defer st.Close()
1308
1309         b := []byte("PROXY TCP6 ::1*foo ::1 12345 8080\r\n")
1310         b[14] = 0
1311         st.conn.Write(b)
1312
1313         _, err := st.http2(requestParam{
1314                 name: "TestH2H1ProxyProtocolV1EmbeddedNULL",
1315         })
1316
1317         if err == nil {
1318                 t.Fatalf("connection was not terminated")
1319         }
1320 }
1321
1322 // TestH2H1ProxyProtocolV1MissingSrcPort tests that PROXY protocol
1323 // version 1 line without src port should be rejected.
1324 func TestH2H1ProxyProtocolV1MissingSrcPort(t *testing.T) {
1325         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1326         defer st.Close()
1327
1328         st.conn.Write([]byte("PROXY TCP6 ::1 ::1  8080\r\n"))
1329
1330         _, err := st.http2(requestParam{
1331                 name: "TestH2H1ProxyProtocolV1MissingSrcPort",
1332         })
1333
1334         if err == nil {
1335                 t.Fatalf("connection was not terminated")
1336         }
1337 }
1338
1339 // TestH2H1ProxyProtocolV1MissingDstPort tests that PROXY protocol
1340 // version 1 line without dst port should be rejected.
1341 func TestH2H1ProxyProtocolV1MissingDstPort(t *testing.T) {
1342         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1343         defer st.Close()
1344
1345         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 \r\n"))
1346
1347         _, err := st.http2(requestParam{
1348                 name: "TestH2H1ProxyProtocolV1MissingDstPort",
1349         })
1350
1351         if err == nil {
1352                 t.Fatalf("connection was not terminated")
1353         }
1354 }
1355
1356 // TestH2H1ProxyProtocolV1InvalidSrcPort tests that PROXY protocol
1357 // containing invalid src port should be rejected.
1358 func TestH2H1ProxyProtocolV1InvalidSrcPort(t *testing.T) {
1359         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1360         defer st.Close()
1361
1362         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 123x 8080\r\n"))
1363
1364         _, err := st.http2(requestParam{
1365                 name: "TestH2H1ProxyProtocolV1InvalidSrcPort",
1366         })
1367
1368         if err == nil {
1369                 t.Fatalf("connection was not terminated")
1370         }
1371 }
1372
1373 // TestH2H1ProxyProtocolV1InvalidDstPort tests that PROXY protocol
1374 // containing invalid dst port should be rejected.
1375 func TestH2H1ProxyProtocolV1InvalidDstPort(t *testing.T) {
1376         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1377         defer st.Close()
1378
1379         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 123456 80x\r\n"))
1380
1381         _, err := st.http2(requestParam{
1382                 name: "TestH2H1ProxyProtocolV1InvalidDstPort",
1383         })
1384
1385         if err == nil {
1386                 t.Fatalf("connection was not terminated")
1387         }
1388 }
1389
1390 // TestH2H1ProxyProtocolV1LeadingZeroPort tests that PROXY protocol
1391 // version 1 line with non zero port with leading zero should be
1392 // rejected.
1393 func TestH2H1ProxyProtocolV1LeadingZeroPort(t *testing.T) {
1394         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1395         defer st.Close()
1396
1397         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 03000 8080\r\n"))
1398
1399         _, err := st.http2(requestParam{
1400                 name: "TestH2H1ProxyProtocolV1LeadingZeroPort",
1401         })
1402
1403         if err == nil {
1404                 t.Fatalf("connection was not terminated")
1405         }
1406 }
1407
1408 // TestH2H1ProxyProtocolV1TooLargeSrcPort tests that PROXY protocol
1409 // containing too large src port should be rejected.
1410 func TestH2H1ProxyProtocolV1TooLargeSrcPort(t *testing.T) {
1411         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1412         defer st.Close()
1413
1414         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 65536 8080\r\n"))
1415
1416         _, err := st.http2(requestParam{
1417                 name: "TestH2H1ProxyProtocolV1TooLargeSrcPort",
1418         })
1419
1420         if err == nil {
1421                 t.Fatalf("connection was not terminated")
1422         }
1423 }
1424
1425 // TestH2H1ProxyProtocolV1TooLargeDstPort tests that PROXY protocol
1426 // containing too large dst port should be rejected.
1427 func TestH2H1ProxyProtocolV1TooLargeDstPort(t *testing.T) {
1428         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1429         defer st.Close()
1430
1431         st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 65536\r\n"))
1432
1433         _, err := st.http2(requestParam{
1434                 name: "TestH2H1ProxyProtocolV1TooLargeDstPort",
1435         })
1436
1437         if err == nil {
1438                 t.Fatalf("connection was not terminated")
1439         }
1440 }
1441
1442 // TestH2H1ProxyProtocolV1InvalidSrcAddr tests that PROXY protocol
1443 // containing invalid src addr should be rejected.
1444 func TestH2H1ProxyProtocolV1InvalidSrcAddr(t *testing.T) {
1445         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1446         defer st.Close()
1447
1448         st.conn.Write([]byte("PROXY TCP6 192.168.0.1 ::1 12345 8080\r\n"))
1449
1450         _, err := st.http2(requestParam{
1451                 name: "TestH2H1ProxyProtocolV1InvalidSrcAddr",
1452         })
1453
1454         if err == nil {
1455                 t.Fatalf("connection was not terminated")
1456         }
1457 }
1458
1459 // TestH2H1ProxyProtocolV1InvalidDstAddr tests that PROXY protocol
1460 // containing invalid dst addr should be rejected.
1461 func TestH2H1ProxyProtocolV1InvalidDstAddr(t *testing.T) {
1462         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1463         defer st.Close()
1464
1465         st.conn.Write([]byte("PROXY TCP6 ::1 192.168.0.1 12345 8080\r\n"))
1466
1467         _, err := st.http2(requestParam{
1468                 name: "TestH2H1ProxyProtocolV1InvalidDstAddr",
1469         })
1470
1471         if err == nil {
1472                 t.Fatalf("connection was not terminated")
1473         }
1474 }
1475
1476 // TestH2H1ProxyProtocolV1InvalidProtoFamily tests that PROXY protocol
1477 // containing invalid protocol family should be rejected.
1478 func TestH2H1ProxyProtocolV1InvalidProtoFamily(t *testing.T) {
1479         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1480         defer st.Close()
1481
1482         st.conn.Write([]byte("PROXY UNIX ::1 ::1 12345 8080\r\n"))
1483
1484         _, err := st.http2(requestParam{
1485                 name: "TestH2H1ProxyProtocolV1InvalidProtoFamily",
1486         })
1487
1488         if err == nil {
1489                 t.Fatalf("connection was not terminated")
1490         }
1491 }
1492
1493 // TestH2H1ProxyProtocolV1InvalidID tests that PROXY protocol
1494 // containing invalid PROXY protocol version 1 ID should be rejected.
1495 func TestH2H1ProxyProtocolV1InvalidID(t *testing.T) {
1496         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1497         defer st.Close()
1498
1499         st.conn.Write([]byte("PR0XY TCP6 ::1 ::1 12345 8080\r\n"))
1500
1501         _, err := st.http2(requestParam{
1502                 name: "TestH2H1ProxyProtocolV1InvalidID",
1503         })
1504
1505         if err == nil {
1506                 t.Fatalf("connection was not terminated")
1507         }
1508 }
1509
1510 // TestH2H1ProxyProtocolV2TCP4 tests PROXY protocol version 2
1511 // containing AF_INET family is accepted and X-Forwarded-For contains
1512 // advertised src address.
1513 func TestH2H1ProxyProtocolV2TCP4(t *testing.T) {
1514         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1515                 if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
1516                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1517                 }
1518                 if got, want := r.Header.Get("Forwarded"), "for=192.168.0.2"; got != want {
1519                         t.Errorf("Forwarded: %v; want %v", got, want)
1520                 }
1521         })
1522         defer st.Close()
1523
1524         var b bytes.Buffer
1525         writeProxyProtocolV2(&b, proxyProtocolV2{
1526                 command: proxyProtocolV2CommandProxy,
1527                 sourceAddress: &net.TCPAddr{
1528                         IP:   net.ParseIP("192.168.0.2").To4(),
1529                         Port: 12345,
1530                 },
1531                 destinationAddress: &net.TCPAddr{
1532                         IP:   net.ParseIP("192.168.0.100").To4(),
1533                         Port: 8080,
1534                 },
1535                 additionalData: []byte("foobar"),
1536         })
1537         st.conn.Write(b.Bytes())
1538
1539         res, err := st.http2(requestParam{
1540                 name: "TestH2H1ProxyProtocolV2TCP4",
1541         })
1542
1543         if err != nil {
1544                 t.Fatalf("Error st.http2() = %v", err)
1545         }
1546
1547         if got, want := res.status, 200; got != want {
1548                 t.Errorf("res.status: %v; want %v", got, want)
1549         }
1550 }
1551
1552 // TestH2H1ProxyProtocolV2TCP6 tests PROXY protocol version 2
1553 // containing AF_INET6 family is accepted and X-Forwarded-For contains
1554 // advertised src address.
1555 func TestH2H1ProxyProtocolV2TCP6(t *testing.T) {
1556         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1557                 if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
1558                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1559                 }
1560                 if got, want := r.Header.Get("Forwarded"), `for="[2001:db8:85a3::8a2e:370:7334]"`; got != want {
1561                         t.Errorf("Forwarded: %v; want %v", got, want)
1562                 }
1563         })
1564         defer st.Close()
1565
1566         var b bytes.Buffer
1567         writeProxyProtocolV2(&b, proxyProtocolV2{
1568                 command: proxyProtocolV2CommandProxy,
1569                 sourceAddress: &net.TCPAddr{
1570                         IP:   net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
1571                         Port: 12345,
1572                 },
1573                 destinationAddress: &net.TCPAddr{
1574                         IP:   net.ParseIP("::1"),
1575                         Port: 8080,
1576                 },
1577                 additionalData: []byte("foobar"),
1578         })
1579         st.conn.Write(b.Bytes())
1580
1581         res, err := st.http2(requestParam{
1582                 name: "TestH2H1ProxyProtocolV2TCP6",
1583         })
1584
1585         if err != nil {
1586                 t.Fatalf("Error st.http2() = %v", err)
1587         }
1588
1589         if got, want := res.status, 200; got != want {
1590                 t.Errorf("res.status: %v; want %v", got, want)
1591         }
1592 }
1593
1594 // TestH2H1ProxyProtocolV2Local tests PROXY protocol version 2
1595 // containing cmd == Local is ignored.
1596 func TestH2H1ProxyProtocolV2Local(t *testing.T) {
1597         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1598                 if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
1599                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1600                 }
1601                 if got, want := r.Header.Get("Forwarded"), "for=127.0.0.1"; got != want {
1602                         t.Errorf("Forwarded: %v; want %v", got, want)
1603                 }
1604         })
1605         defer st.Close()
1606
1607         var b bytes.Buffer
1608         writeProxyProtocolV2(&b, proxyProtocolV2{
1609                 command: proxyProtocolV2CommandLocal,
1610                 sourceAddress: &net.TCPAddr{
1611                         IP:   net.ParseIP("192.168.0.2").To4(),
1612                         Port: 12345,
1613                 },
1614                 destinationAddress: &net.TCPAddr{
1615                         IP:   net.ParseIP("192.168.0.100").To4(),
1616                         Port: 8080,
1617                 },
1618                 additionalData: []byte("foobar"),
1619         })
1620         st.conn.Write(b.Bytes())
1621
1622         res, err := st.http2(requestParam{
1623                 name: "TestH2H1ProxyProtocolV2Local",
1624         })
1625
1626         if err != nil {
1627                 t.Fatalf("Error st.http2() = %v", err)
1628         }
1629
1630         if got, want := res.status, 200; got != want {
1631                 t.Errorf("res.status: %v; want %v", got, want)
1632         }
1633 }
1634
1635 // TestH2H1ProxyProtocolV2UnknownCmd tests PROXY protocol version 2
1636 // containing unknown cmd should be rejected.
1637 func TestH2H1ProxyProtocolV2UnknownCmd(t *testing.T) {
1638         st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
1639         defer st.Close()
1640
1641         var b bytes.Buffer
1642         writeProxyProtocolV2(&b, proxyProtocolV2{
1643                 command: 0xf,
1644                 sourceAddress: &net.TCPAddr{
1645                         IP:   net.ParseIP("192.168.0.2").To4(),
1646                         Port: 12345,
1647                 },
1648                 destinationAddress: &net.TCPAddr{
1649                         IP:   net.ParseIP("192.168.0.100").To4(),
1650                         Port: 8080,
1651                 },
1652                 additionalData: []byte("foobar"),
1653         })
1654         st.conn.Write(b.Bytes())
1655
1656         _, err := st.http2(requestParam{
1657                 name: "TestH2H1ProxyProtocolV2UnknownCmd",
1658         })
1659
1660         if err == nil {
1661                 t.Fatalf("connection was not terminated")
1662         }
1663 }
1664
1665 // TestH2H1ProxyProtocolV2Unix tests PROXY protocol version 2
1666 // containing AF_UNIX family is ignored.
1667 func TestH2H1ProxyProtocolV2Unix(t *testing.T) {
1668         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1669                 if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
1670                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1671                 }
1672                 if got, want := r.Header.Get("Forwarded"), "for=127.0.0.1"; got != want {
1673                         t.Errorf("Forwarded: %v; want %v", got, want)
1674                 }
1675         })
1676         defer st.Close()
1677
1678         var b bytes.Buffer
1679         writeProxyProtocolV2(&b, proxyProtocolV2{
1680                 command: proxyProtocolV2CommandProxy,
1681                 sourceAddress: &net.UnixAddr{
1682                         Name: "/foo",
1683                         Net:  "unix",
1684                 },
1685                 destinationAddress: &net.UnixAddr{
1686                         Name: "/bar",
1687                         Net:  "unix",
1688                 },
1689                 additionalData: []byte("foobar"),
1690         })
1691         st.conn.Write(b.Bytes())
1692
1693         res, err := st.http2(requestParam{
1694                 name: "TestH2H1ProxyProtocolV2Unix",
1695         })
1696
1697         if err != nil {
1698                 t.Fatalf("Error st.http2() = %v", err)
1699         }
1700
1701         if got, want := res.status, 200; got != want {
1702                 t.Errorf("res.status: %v; want %v", got, want)
1703         }
1704 }
1705
1706 // TestH2H1ProxyProtocolV2Unspec tests PROXY protocol version 2
1707 // containing AF_UNSPEC family is ignored.
1708 func TestH2H1ProxyProtocolV2Unspec(t *testing.T) {
1709         st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
1710                 if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
1711                         t.Errorf("X-Forwarded-For: %v; want %v", got, want)
1712                 }
1713                 if got, want := r.Header.Get("Forwarded"), "for=127.0.0.1"; got != want {
1714                         t.Errorf("Forwarded: %v; want %v", got, want)
1715                 }
1716         })
1717         defer st.Close()
1718
1719         var b bytes.Buffer
1720         writeProxyProtocolV2(&b, proxyProtocolV2{
1721                 command:        proxyProtocolV2CommandProxy,
1722                 additionalData: []byte("foobar"),
1723         })
1724         st.conn.Write(b.Bytes())
1725
1726         res, err := st.http2(requestParam{
1727                 name: "TestH2H1ProxyProtocolV2Unspec",
1728         })
1729
1730         if err != nil {
1731                 t.Fatalf("Error st.http2() = %v", err)
1732         }
1733
1734         if got, want := res.status, 200; got != want {
1735                 t.Errorf("res.status: %v; want %v", got, want)
1736         }
1737 }
1738
1739 // TestH2H1ExternalDNS tests that DNS resolution using external DNS
1740 // with HTTP/1 backend works.
1741 func TestH2H1ExternalDNS(t *testing.T) {
1742         st := newServerTester([]string{"--external-dns"}, t, noopHandler)
1743         defer st.Close()
1744
1745         res, err := st.http2(requestParam{
1746                 name: "TestH2H1ExternalDNS",
1747         })
1748         if err != nil {
1749                 t.Fatalf("Error st.http2() = %v", err)
1750         }
1751
1752         if got, want := res.status, 200; got != want {
1753                 t.Errorf("status = %v; want %v", got, want)
1754         }
1755 }
1756
1757 // TestH2H1DNS tests that DNS resolution without external DNS with
1758 // HTTP/1 backend works.
1759 func TestH2H1DNS(t *testing.T) {
1760         st := newServerTester([]string{"--dns"}, t, noopHandler)
1761         defer st.Close()
1762
1763         res, err := st.http2(requestParam{
1764                 name: "TestH2H1DNS",
1765         })
1766         if err != nil {
1767                 t.Fatalf("Error st.http2() = %v", err)
1768         }
1769
1770         if got, want := res.status, 200; got != want {
1771                 t.Errorf("status = %v; want %v", got, want)
1772         }
1773 }
1774
1775 // TestH2H1HTTPSRedirect tests that the request to the backend which
1776 // requires TLS is redirected to https URI.
1777 func TestH2H1HTTPSRedirect(t *testing.T) {
1778         st := newServerTester([]string{"--redirect-if-not-tls"}, t, noopHandler)
1779         defer st.Close()
1780
1781         res, err := st.http2(requestParam{
1782                 name: "TestH2H1HTTPSRedirect",
1783         })
1784         if err != nil {
1785                 t.Fatalf("Error st.http2() = %v", err)
1786         }
1787
1788         if got, want := res.status, 308; got != want {
1789                 t.Errorf("status = %v; want %v", got, want)
1790         }
1791         if got, want := res.header.Get("location"), "https://127.0.0.1/"; got != want {
1792                 t.Errorf("location: %v; want %v", got, want)
1793         }
1794 }
1795
1796 // TestH2H1HTTPSRedirectPort tests that the request to the backend
1797 // which requires TLS is redirected to https URI with given port.
1798 func TestH2H1HTTPSRedirectPort(t *testing.T) {
1799         st := newServerTester([]string{"--redirect-if-not-tls", "--redirect-https-port=8443"}, t, noopHandler)
1800         defer st.Close()
1801
1802         res, err := st.http2(requestParam{
1803                 path: "/foo?bar",
1804                 name: "TestH2H1HTTPSRedirectPort",
1805         })
1806         if err != nil {
1807                 t.Fatalf("Error st.http2() = %v", err)
1808         }
1809
1810         if got, want := res.status, 308; got != want {
1811                 t.Errorf("status = %v; want %v", got, want)
1812         }
1813         if got, want := res.header.Get("location"), "https://127.0.0.1:8443/foo?bar"; got != want {
1814                 t.Errorf("location: %v; want %v", got, want)
1815         }
1816 }
1817
1818 // TestH2H1Code204 tests that 204 response without content-length, and
1819 // transfer-encoding is valid.
1820 func TestH2H1Code204(t *testing.T) {
1821         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
1822                 w.WriteHeader(http.StatusNoContent)
1823         })
1824         defer st.Close()
1825
1826         res, err := st.http2(requestParam{
1827                 name: "TestH2H1Code204",
1828         })
1829         if err != nil {
1830                 t.Fatalf("Error st.http2() = %v", err)
1831         }
1832
1833         if got, want := res.status, 204; got != want {
1834                 t.Errorf("status = %v; want %v", got, want)
1835         }
1836 }
1837
1838 // TestH2H1Code204CL0 tests that 204 response with content-length: 0
1839 // is allowed.
1840 func TestH2H1Code204CL0(t *testing.T) {
1841         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
1842                 hj, ok := w.(http.Hijacker)
1843                 if !ok {
1844                         http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
1845                         return
1846                 }
1847                 conn, bufrw, err := hj.Hijack()
1848                 if err != nil {
1849                         http.Error(w, err.Error(), http.StatusInternalServerError)
1850                         return
1851                 }
1852                 defer conn.Close()
1853                 bufrw.WriteString("HTTP/1.1 204\r\nContent-Length: 0\r\n\r\n")
1854                 bufrw.Flush()
1855         })
1856         defer st.Close()
1857
1858         res, err := st.http2(requestParam{
1859                 name: "TestH2H1Code204CL0",
1860         })
1861         if err != nil {
1862                 t.Fatalf("Error st.http2() = %v", err)
1863         }
1864
1865         if got, want := res.status, 204; got != want {
1866                 t.Errorf("status = %v; want %v", got, want)
1867         }
1868
1869         if got, found := res.header["Content-Length"]; found {
1870                 t.Errorf("Content-Length = %v, want nothing", got)
1871         }
1872 }
1873
1874 // TestH2H1Code204CLNonzero tests that 204 response with nonzero
1875 // content-length is not allowed.
1876 func TestH2H1Code204CLNonzero(t *testing.T) {
1877         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
1878                 hj, ok := w.(http.Hijacker)
1879                 if !ok {
1880                         http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
1881                         return
1882                 }
1883                 conn, bufrw, err := hj.Hijack()
1884                 if err != nil {
1885                         http.Error(w, err.Error(), http.StatusInternalServerError)
1886                         return
1887                 }
1888                 defer conn.Close()
1889                 bufrw.WriteString("HTTP/1.1 204\r\nContent-Length: 1\r\n\r\n")
1890                 bufrw.Flush()
1891         })
1892         defer st.Close()
1893
1894         res, err := st.http2(requestParam{
1895                 name: "TestH2H1Code204CLNonzero",
1896         })
1897         if err != nil {
1898                 t.Fatalf("Error st.http2() = %v", err)
1899         }
1900
1901         if got, want := res.status, 502; got != want {
1902                 t.Errorf("status = %v; want %v", got, want)
1903         }
1904 }
1905
1906 // TestH2H1Code204TE tests that 204 response with transfer-encoding is
1907 // not allowed.
1908 func TestH2H1Code204TE(t *testing.T) {
1909         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
1910                 hj, ok := w.(http.Hijacker)
1911                 if !ok {
1912                         http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
1913                         return
1914                 }
1915                 conn, bufrw, err := hj.Hijack()
1916                 if err != nil {
1917                         http.Error(w, err.Error(), http.StatusInternalServerError)
1918                         return
1919                 }
1920                 defer conn.Close()
1921                 bufrw.WriteString("HTTP/1.1 204\r\nTransfer-Encoding: chunked\r\n\r\n")
1922                 bufrw.Flush()
1923         })
1924         defer st.Close()
1925
1926         res, err := st.http2(requestParam{
1927                 name: "TestH2H1Code204TE",
1928         })
1929         if err != nil {
1930                 t.Fatalf("Error st.http2() = %v", err)
1931         }
1932
1933         if got, want := res.status, 502; got != want {
1934                 t.Errorf("status = %v; want %v", got, want)
1935         }
1936 }
1937
1938 // TestH2H1AffinityCookie tests that affinity cookie is sent back in
1939 // cleartext http.
1940 func TestH2H1AffinityCookie(t *testing.T) {
1941         st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler)
1942         defer st.Close()
1943
1944         res, err := st.http2(requestParam{
1945                 name: "TestH2H1AffinityCookie",
1946         })
1947         if err != nil {
1948                 t.Fatalf("Error st.http2() = %v", err)
1949         }
1950
1951         if got, want := res.status, 200; got != want {
1952                 t.Errorf("status = %v; want %v", got, want)
1953         }
1954
1955         const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
1956         validCookie := regexp.MustCompile(pattern)
1957         if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
1958                 t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
1959         }
1960 }
1961
1962 // TestH2H1AffinityCookieTLS tests that affinity cookie is sent back
1963 // in https.
1964 func TestH2H1AffinityCookieTLS(t *testing.T) {
1965         st := newServerTesterTLS([]string{"--affinity-cookie"}, t, noopHandler)
1966         defer st.Close()
1967
1968         res, err := st.http2(requestParam{
1969                 name:   "TestH2H1AffinityCookieTLS",
1970                 scheme: "https",
1971         })
1972         if err != nil {
1973                 t.Fatalf("Error st.http2() = %v", err)
1974         }
1975
1976         if got, want := res.status, 200; got != want {
1977                 t.Errorf("status = %v; want %v", got, want)
1978         }
1979
1980         const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
1981         validCookie := regexp.MustCompile(pattern)
1982         if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
1983                 t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
1984         }
1985 }
1986
1987 // TestH2H1GracefulShutdown tests graceful shutdown.
1988 func TestH2H1GracefulShutdown(t *testing.T) {
1989         st := newServerTester(nil, t, noopHandler)
1990         defer st.Close()
1991
1992         fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
1993         if err := st.fr.WriteSettings(); err != nil {
1994                 t.Fatalf("st.fr.WriteSettings(): %v", err)
1995         }
1996
1997         header := []hpack.HeaderField{
1998                 pair(":method", "GET"),
1999                 pair(":scheme", "http"),
2000                 pair(":authority", st.authority),
2001                 pair(":path", "/"),
2002         }
2003
2004         for _, h := range header {
2005                 _ = st.enc.WriteField(h)
2006         }
2007
2008         if err := st.fr.WriteHeaders(http2.HeadersFrameParam{
2009                 StreamID:      1,
2010                 EndStream:     false,
2011                 EndHeaders:    true,
2012                 BlockFragment: st.headerBlkBuf.Bytes(),
2013         }); err != nil {
2014                 t.Fatalf("st.fr.WriteHeaders(): %v", err)
2015         }
2016
2017         // send SIGQUIT signal to nghttpx to perform graceful shutdown
2018         st.cmd.Process.Signal(syscall.SIGQUIT)
2019         time.Sleep(150 * time.Millisecond)
2020
2021         // after signal, finish request body
2022         if err := st.fr.WriteData(1, true, nil); err != nil {
2023                 t.Fatalf("st.fr.WriteData(): %v", err)
2024         }
2025
2026         numGoAway := 0
2027
2028         for {
2029                 fr, err := st.readFrame()
2030                 if err != nil {
2031                         if err == io.EOF {
2032                                 want := 2
2033                                 if got := numGoAway; got != want {
2034                                         t.Fatalf("numGoAway: %v; want %v", got, want)
2035                                 }
2036                                 return
2037                         }
2038                         t.Fatalf("st.readFrame(): %v", err)
2039                 }
2040                 switch f := fr.(type) {
2041                 case *http2.GoAwayFrame:
2042                         numGoAway += 1
2043                         want := http2.ErrCodeNo
2044                         if got := f.ErrCode; got != want {
2045                                 t.Fatalf("f.ErrCode(%v): %v; want %v", numGoAway, got, want)
2046                         }
2047                         switch numGoAway {
2048                         case 1:
2049                                 want := (uint32(1) << 31) - 1
2050                                 if got := f.LastStreamID; got != want {
2051                                         t.Fatalf("f.LastStreamID(%v): %v; want %v", numGoAway, got, want)
2052                                 }
2053                         case 2:
2054                                 want := uint32(1)
2055                                 if got := f.LastStreamID; got != want {
2056                                         t.Fatalf("f.LastStreamID(%v): %v; want %v", numGoAway, got, want)
2057                                 }
2058                         case 3:
2059                                 t.Fatalf("too many GOAWAYs received")
2060                         }
2061                 }
2062         }
2063 }
2064
2065 // TestH2H2MultipleResponseCL tests that server returns error if
2066 // multiple Content-Length response header fields are received.
2067 func TestH2H2MultipleResponseCL(t *testing.T) {
2068         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
2069                 w.Header().Add("content-length", "1")
2070                 w.Header().Add("content-length", "1")
2071         })
2072         defer st.Close()
2073
2074         res, err := st.http2(requestParam{
2075                 name: "TestH2H2MultipleResponseCL",
2076         })
2077         if err != nil {
2078                 t.Fatalf("Error st.http2() = %v", err)
2079         }
2080         if got, want := res.errCode, http2.ErrCodeInternal; got != want {
2081                 t.Errorf("res.errCode: %v; want %v", got, want)
2082         }
2083 }
2084
2085 // TestH2H2InvalidResponseCL tests that server returns error if
2086 // Content-Length response header field value cannot be parsed as a
2087 // number.
2088 func TestH2H2InvalidResponseCL(t *testing.T) {
2089         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
2090                 w.Header().Add("content-length", "")
2091         })
2092         defer st.Close()
2093
2094         res, err := st.http2(requestParam{
2095                 name: "TestH2H2InvalidResponseCL",
2096         })
2097         if err != nil {
2098                 t.Fatalf("Error st.http2() = %v", err)
2099         }
2100         if got, want := res.errCode, http2.ErrCodeInternal; got != want {
2101                 t.Errorf("res.errCode: %v; want %v", got, want)
2102         }
2103 }
2104
2105 // // TestH2H2ConnectFailure tests that server handles the situation that
2106 // // connection attempt to HTTP/2 backend failed.
2107 // func TestH2H2ConnectFailure(t *testing.T) {
2108 //      st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
2109 //      defer st.Close()
2110
2111 //      // simulate backend connect attempt failure
2112 //      st.ts.Close()
2113
2114 //      res, err := st.http2(requestParam{
2115 //              name: "TestH2H2ConnectFailure",
2116 //      })
2117 //      if err != nil {
2118 //              t.Fatalf("Error st.http2() = %v", err)
2119 //      }
2120 //      want := 503
2121 //      if got := res.status; got != want {
2122 //              t.Errorf("status: %v; want %v", got, want)
2123 //      }
2124 // }
2125
2126 // TestH2H2HostRewrite tests that server rewrites host header field
2127 func TestH2H2HostRewrite(t *testing.T) {
2128         st := newServerTester([]string{"--http2-bridge", "--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
2129                 w.Header().Add("request-host", r.Host)
2130         })
2131         defer st.Close()
2132
2133         res, err := st.http2(requestParam{
2134                 name: "TestH2H2HostRewrite",
2135         })
2136         if err != nil {
2137                 t.Fatalf("Error st.http2() = %v", err)
2138         }
2139         if got, want := res.status, 200; got != want {
2140                 t.Errorf("status: %v; want %v", got, want)
2141         }
2142         if got, want := res.header.Get("request-host"), st.backendHost; got != want {
2143                 t.Errorf("request-host: %v; want %v", got, want)
2144         }
2145 }
2146
2147 // TestH2H2NoHostRewrite tests that server does not rewrite host
2148 // header field
2149 func TestH2H2NoHostRewrite(t *testing.T) {
2150         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
2151                 w.Header().Add("request-host", r.Host)
2152         })
2153         defer st.Close()
2154
2155         res, err := st.http2(requestParam{
2156                 name: "TestH2H2NoHostRewrite",
2157         })
2158         if err != nil {
2159                 t.Fatalf("Error st.http2() = %v", err)
2160         }
2161         if got, want := res.status, 200; got != want {
2162                 t.Errorf("status: %v; want %v", got, want)
2163         }
2164         if got, want := res.header.Get("request-host"), st.frontendHost; got != want {
2165                 t.Errorf("request-host: %v; want %v", got, want)
2166         }
2167 }
2168
2169 // TestH2H2TLSXfp tests nghttpx sends x-forwarded-proto header field
2170 // with http value since :scheme is http, even if the frontend
2171 // connection is encrypted.
2172 func TestH2H2TLSXfp(t *testing.T) {
2173         st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
2174                 if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
2175                         t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
2176                 }
2177         })
2178         defer st.Close()
2179
2180         res, err := st.http2(requestParam{
2181                 name: "TestH2H2TLSXfp",
2182         })
2183         if err != nil {
2184                 t.Fatalf("Error st.http2() = %v", err)
2185         }
2186         if got, want := res.status, 200; got != want {
2187                 t.Errorf("res.status: %v; want %v", got, want)
2188         }
2189 }
2190
2191 // TestH2H2AddXfp tests that server appends :scheme to the existing
2192 // x-forwarded-proto header field.
2193 func TestH2H2AddXfp(t *testing.T) {
2194         st := newServerTesterTLS([]string{"--http2-bridge", "--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
2195                 xfp := r.Header.Get("X-Forwarded-Proto")
2196                 if got, want := xfp, "foo, http"; got != want {
2197                         t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
2198                 }
2199         })
2200         defer st.Close()
2201
2202         res, err := st.http2(requestParam{
2203                 name: "TestH2H2AddXfp",
2204                 header: []hpack.HeaderField{
2205                         pair("x-forwarded-proto", "foo"),
2206                 },
2207         })
2208         if err != nil {
2209                 t.Fatalf("Error st.http2() = %v", err)
2210         }
2211         if got, want := res.status, 200; got != want {
2212                 t.Errorf("status = %v; want %v", got, want)
2213         }
2214 }
2215
2216 // TestH2H2NoAddXfp tests that server does not append :scheme to the
2217 // existing x-forwarded-proto header field.
2218 func TestH2H2NoAddXfp(t *testing.T) {
2219         st := newServerTesterTLS([]string{"--http2-bridge", "--no-add-x-forwarded-proto", "--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
2220                 xfp := r.Header.Get("X-Forwarded-Proto")
2221                 if got, want := xfp, "foo"; got != want {
2222                         t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
2223                 }
2224         })
2225         defer st.Close()
2226
2227         res, err := st.http2(requestParam{
2228                 name: "TestH2H2NoAddXfp",
2229                 header: []hpack.HeaderField{
2230                         pair("x-forwarded-proto", "foo"),
2231                 },
2232         })
2233         if err != nil {
2234                 t.Fatalf("Error st.http2() = %v", err)
2235         }
2236         if got, want := res.status, 200; got != want {
2237                 t.Errorf("status = %v; want %v", got, want)
2238         }
2239 }
2240
2241 // TestH2H2StripXfp tests that server strips incoming
2242 // x-forwarded-proto header field.
2243 func TestH2H2StripXfp(t *testing.T) {
2244         st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
2245                 xfp := r.Header.Get("X-Forwarded-Proto")
2246                 if got, want := xfp, "http"; got != want {
2247                         t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
2248                 }
2249         })
2250         defer st.Close()
2251
2252         res, err := st.http2(requestParam{
2253                 name: "TestH2H2StripXfp",
2254                 header: []hpack.HeaderField{
2255                         pair("x-forwarded-proto", "foo"),
2256                 },
2257         })
2258         if err != nil {
2259                 t.Fatalf("Error st.http2() = %v", err)
2260         }
2261         if got, want := res.status, 200; got != want {
2262                 t.Errorf("status = %v; want %v", got, want)
2263         }
2264 }
2265
2266 // TestH2H2StripNoAddXfp tests that server strips incoming
2267 // x-forwarded-proto header field, and does not add another.
2268 func TestH2H2StripNoAddXfp(t *testing.T) {
2269         st := newServerTesterTLS([]string{"--http2-bridge", "--no-add-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
2270                 if got, found := r.Header["X-Forwarded-Proto"]; found {
2271                         t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
2272                 }
2273         })
2274         defer st.Close()
2275
2276         res, err := st.http2(requestParam{
2277                 name: "TestH2H2StripNoAddXfp",
2278                 header: []hpack.HeaderField{
2279                         pair("x-forwarded-proto", "foo"),
2280                 },
2281         })
2282         if err != nil {
2283                 t.Fatalf("Error st.http2() = %v", err)
2284         }
2285         if got, want := res.status, 200; got != want {
2286                 t.Errorf("status = %v; want %v", got, want)
2287         }
2288 }
2289
2290 // TestH2H2AddXff tests that server generates X-Forwarded-For header
2291 // field when forwarding request to backend.
2292 func TestH2H2AddXff(t *testing.T) {
2293         st := newServerTesterTLS([]string{"--http2-bridge", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
2294                 xff := r.Header.Get("X-Forwarded-For")
2295                 want := "127.0.0.1"
2296                 if xff != want {
2297                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
2298                 }
2299         })
2300         defer st.Close()
2301
2302         res, err := st.http2(requestParam{
2303                 name: "TestH2H2AddXff",
2304         })
2305         if err != nil {
2306                 t.Fatalf("Error st.http2() = %v", err)
2307         }
2308         if got, want := res.status, 200; got != want {
2309                 t.Errorf("status = %v; want %v", got, want)
2310         }
2311 }
2312
2313 // TestH2H2AddXff2 tests that server appends X-Forwarded-For header
2314 // field to existing one when forwarding request to backend.
2315 func TestH2H2AddXff2(t *testing.T) {
2316         st := newServerTesterTLS([]string{"--http2-bridge", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
2317                 xff := r.Header.Get("X-Forwarded-For")
2318                 want := "host, 127.0.0.1"
2319                 if xff != want {
2320                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
2321                 }
2322         })
2323         defer st.Close()
2324
2325         res, err := st.http2(requestParam{
2326                 name: "TestH2H2AddXff2",
2327                 header: []hpack.HeaderField{
2328                         pair("x-forwarded-for", "host"),
2329                 },
2330         })
2331         if err != nil {
2332                 t.Fatalf("Error st.http2() = %v", err)
2333         }
2334         if got, want := res.status, 200; got != want {
2335                 t.Errorf("status = %v; want %v", got, want)
2336         }
2337 }
2338
2339 // TestH2H2StripXff tests that --strip-incoming-x-forwarded-for
2340 // option.
2341 func TestH2H2StripXff(t *testing.T) {
2342         st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
2343                 if xff, found := r.Header["X-Forwarded-For"]; found {
2344                         t.Errorf("X-Forwarded-For = %v; want nothing", xff)
2345                 }
2346         })
2347         defer st.Close()
2348
2349         res, err := st.http2(requestParam{
2350                 name: "TestH2H2StripXff",
2351                 header: []hpack.HeaderField{
2352                         pair("x-forwarded-for", "host"),
2353                 },
2354         })
2355         if err != nil {
2356                 t.Fatalf("Error st.http2() = %v", err)
2357         }
2358         if got, want := res.status, 200; got != want {
2359                 t.Errorf("status = %v; want %v", got, want)
2360         }
2361 }
2362
2363 // TestH2H2StripAddXff tests that --strip-incoming-x-forwarded-for and
2364 // --add-x-forwarded-for options.
2365 func TestH2H2StripAddXff(t *testing.T) {
2366         st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-x-forwarded-for", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
2367                 xff := r.Header.Get("X-Forwarded-For")
2368                 want := "127.0.0.1"
2369                 if xff != want {
2370                         t.Errorf("X-Forwarded-For = %v; want %v", xff, want)
2371                 }
2372         })
2373         defer st.Close()
2374
2375         res, err := st.http2(requestParam{
2376                 name: "TestH2H2StripAddXff",
2377                 header: []hpack.HeaderField{
2378                         pair("x-forwarded-for", "host"),
2379                 },
2380         })
2381         if err != nil {
2382                 t.Fatalf("Error st.http2() = %v", err)
2383         }
2384         if got, want := res.status, 200; got != want {
2385                 t.Errorf("status = %v; want %v", got, want)
2386         }
2387 }
2388
2389 // TestH2H2AddForwarded tests that server generates Forwarded header
2390 // field using static obfuscated "by" parameter.
2391 func TestH2H2AddForwarded(t *testing.T) {
2392         st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
2393                 pattern := fmt.Sprintf(`by=_alpha;for=_[^;]+;host="127\.0\.0\.1:%v";proto=https`, serverPort)
2394                 validFwd := regexp.MustCompile(pattern)
2395                 if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
2396                         t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
2397                 }
2398         })
2399         defer st.Close()
2400
2401         res, err := st.http2(requestParam{
2402                 name:   "TestH2H2AddForwarded",
2403                 scheme: "https",
2404         })
2405         if err != nil {
2406                 t.Fatalf("Error st.http2() = %v", err)
2407         }
2408         if got, want := res.status, 200; got != want {
2409                 t.Errorf("status: %v; want %v", got, want)
2410         }
2411 }
2412
2413 // TestH2H2AddForwardedMerge tests that server generates Forwarded
2414 // header field using static obfuscated "by" parameter, and
2415 // existing Forwarded header field.
2416 func TestH2H2AddForwardedMerge(t *testing.T) {
2417         st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
2418                 want := fmt.Sprintf(`host=foo, by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
2419                 if got := r.Header.Get("Forwarded"); got != want {
2420                         t.Errorf("Forwarded = %v; want %v", got, want)
2421                 }
2422         })
2423         defer st.Close()
2424
2425         res, err := st.http2(requestParam{
2426                 name:   "TestH2H2AddForwardedMerge",
2427                 scheme: "https",
2428                 header: []hpack.HeaderField{
2429                         pair("forwarded", "host=foo"),
2430                 },
2431         })
2432         if err != nil {
2433                 t.Fatalf("Error st.http2() = %v", err)
2434         }
2435         if got, want := res.status, 200; got != want {
2436                 t.Errorf("status: %v; want %v", got, want)
2437         }
2438 }
2439
2440 // TestH2H2AddForwardedStrip tests that server generates Forwarded
2441 // header field using static obfuscated "by" parameter, and
2442 // existing Forwarded header field stripped.
2443 func TestH2H2AddForwardedStrip(t *testing.T) {
2444         st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-forwarded", "--add-forwarded=by,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
2445                 want := fmt.Sprintf(`by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
2446                 if got := r.Header.Get("Forwarded"); got != want {
2447                         t.Errorf("Forwarded = %v; want %v", got, want)
2448                 }
2449         })
2450         defer st.Close()
2451
2452         res, err := st.http2(requestParam{
2453                 name:   "TestH2H2AddForwardedStrip",
2454                 scheme: "https",
2455                 header: []hpack.HeaderField{
2456                         pair("forwarded", "host=foo"),
2457                 },
2458         })
2459         if err != nil {
2460                 t.Fatalf("Error st.http2() = %v", err)
2461         }
2462         if got, want := res.status, 200; got != want {
2463                 t.Errorf("status: %v; want %v", got, want)
2464         }
2465 }
2466
2467 // TestH2H2StripForwarded tests that server strips incoming Forwarded
2468 // header field.
2469 func TestH2H2StripForwarded(t *testing.T) {
2470         st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-forwarded"}, t, func(w http.ResponseWriter, r *http.Request) {
2471                 if got, found := r.Header["Forwarded"]; found {
2472                         t.Errorf("Forwarded = %v; want nothing", got)
2473                 }
2474         })
2475         defer st.Close()
2476
2477         res, err := st.http2(requestParam{
2478                 name:   "TestH2H2StripForwarded",
2479                 scheme: "https",
2480                 header: []hpack.HeaderField{
2481                         pair("forwarded", "host=foo"),
2482                 },
2483         })
2484         if err != nil {
2485                 t.Fatalf("Error st.http2() = %v", err)
2486         }
2487         if got, want := res.status, 200; got != want {
2488                 t.Errorf("status: %v; want %v", got, want)
2489         }
2490 }
2491
2492 // TestH2H2ReqPhaseReturn tests mruby request phase hook returns
2493 // custom response.
2494 func TestH2H2ReqPhaseReturn(t *testing.T) {
2495         st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
2496                 t.Fatalf("request should not be forwarded")
2497         })
2498         defer st.Close()
2499
2500         res, err := st.http2(requestParam{
2501                 name: "TestH2H2ReqPhaseReturn",
2502         })
2503         if err != nil {
2504                 t.Fatalf("Error st.http2() = %v", err)
2505         }
2506
2507         if got, want := res.status, 404; got != want {
2508                 t.Errorf("status = %v; want %v", got, want)
2509         }
2510
2511         hdtests := []struct {
2512                 k, v string
2513         }{
2514                 {"content-length", "20"},
2515                 {"from", "mruby"},
2516         }
2517         for _, tt := range hdtests {
2518                 if got, want := res.header.Get(tt.k), tt.v; got != want {
2519                         t.Errorf("%v = %v; want %v", tt.k, got, want)
2520                 }
2521         }
2522
2523         if got, want := string(res.body), "Hello World from req"; got != want {
2524                 t.Errorf("body = %v; want %v", got, want)
2525         }
2526 }
2527
2528 // TestH2H2RespPhaseReturn tests mruby response phase hook returns
2529 // custom response.
2530 func TestH2H2RespPhaseReturn(t *testing.T) {
2531         st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
2532         defer st.Close()
2533
2534         res, err := st.http2(requestParam{
2535                 name: "TestH2H2RespPhaseReturn",
2536         })
2537         if err != nil {
2538                 t.Fatalf("Error st.http2() = %v", err)
2539         }
2540
2541         if got, want := res.status, 404; got != want {
2542                 t.Errorf("status = %v; want %v", got, want)
2543         }
2544
2545         hdtests := []struct {
2546                 k, v string
2547         }{
2548                 {"content-length", "21"},
2549                 {"from", "mruby"},
2550         }
2551         for _, tt := range hdtests {
2552                 if got, want := res.header.Get(tt.k), tt.v; got != want {
2553                         t.Errorf("%v = %v; want %v", tt.k, got, want)
2554                 }
2555         }
2556
2557         if got, want := string(res.body), "Hello World from resp"; got != want {
2558                 t.Errorf("body = %v; want %v", got, want)
2559         }
2560 }
2561
2562 // TestH2H2ExternalDNS tests that DNS resolution using external DNS
2563 // with HTTP/2 backend works.
2564 func TestH2H2ExternalDNS(t *testing.T) {
2565         st := newServerTester([]string{"--http2-bridge", "--external-dns"}, t, noopHandler)
2566         defer st.Close()
2567
2568         res, err := st.http2(requestParam{
2569                 name: "TestH2H2ExternalDNS",
2570         })
2571         if err != nil {
2572                 t.Fatalf("Error st.http2() = %v", err)
2573         }
2574
2575         if got, want := res.status, 200; got != want {
2576                 t.Errorf("status = %v; want %v", got, want)
2577         }
2578 }
2579
2580 // TestH2H2DNS tests that DNS resolution without external DNS with
2581 // HTTP/2 backend works.
2582 func TestH2H2DNS(t *testing.T) {
2583         st := newServerTester([]string{"--http2-bridge", "--dns"}, t, noopHandler)
2584         defer st.Close()
2585
2586         res, err := st.http2(requestParam{
2587                 name: "TestH2H2DNS",
2588         })
2589         if err != nil {
2590                 t.Fatalf("Error st.http2() = %v", err)
2591         }
2592
2593         if got, want := res.status, 200; got != want {
2594                 t.Errorf("status = %v; want %v", got, want)
2595         }
2596 }
2597
2598 // TestH2H2Code204 tests that 204 response without content-length, and
2599 // transfer-encoding is valid.
2600 func TestH2H2Code204(t *testing.T) {
2601         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
2602                 w.WriteHeader(http.StatusNoContent)
2603         })
2604         defer st.Close()
2605
2606         res, err := st.http2(requestParam{
2607                 name: "TestH2H2Code204",
2608         })
2609         if err != nil {
2610                 t.Fatalf("Error st.http2() = %v", err)
2611         }
2612
2613         if got, want := res.status, 204; got != want {
2614                 t.Errorf("status = %v; want %v", got, want)
2615         }
2616 }
2617
2618 // TestH2APIBackendconfig exercise backendconfig API endpoint routine
2619 // for successful case.
2620 func TestH2APIBackendconfig(t *testing.T) {
2621         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
2622                 t.Fatalf("request should not be forwarded")
2623         }, 3010)
2624         defer st.Close()
2625
2626         res, err := st.http2(requestParam{
2627                 name:   "TestH2APIBackendconfig",
2628                 path:   "/api/v1beta1/backendconfig",
2629                 method: "PUT",
2630                 body: []byte(`# comment
2631 backend=127.0.0.1,3011
2632
2633 `),
2634         })
2635         if err != nil {
2636                 t.Fatalf("Error st.http2() = %v", err)
2637         }
2638         if got, want := res.status, 200; got != want {
2639                 t.Errorf("res.status: %v; want %v", got, want)
2640         }
2641
2642         var apiResp APIResponse
2643         err = json.Unmarshal(res.body, &apiResp)
2644         if err != nil {
2645                 t.Fatalf("Error unmarshaling API response: %v", err)
2646         }
2647         if got, want := apiResp.Status, "Success"; got != want {
2648                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2649         }
2650         if got, want := apiResp.Code, 200; got != want {
2651                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2652         }
2653 }
2654
2655 // TestH2APIBackendconfigQuery exercise backendconfig API endpoint
2656 // routine with query.
2657 func TestH2APIBackendconfigQuery(t *testing.T) {
2658         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
2659                 t.Fatalf("request should not be forwarded")
2660         }, 3010)
2661         defer st.Close()
2662
2663         res, err := st.http2(requestParam{
2664                 name:   "TestH2APIBackendconfigQuery",
2665                 path:   "/api/v1beta1/backendconfig?foo=bar",
2666                 method: "PUT",
2667                 body: []byte(`# comment
2668 backend=127.0.0.1,3011
2669
2670 `),
2671         })
2672         if err != nil {
2673                 t.Fatalf("Error st.http2() = %v", err)
2674         }
2675         if got, want := res.status, 200; got != want {
2676                 t.Errorf("res.status: %v; want %v", got, want)
2677         }
2678
2679         var apiResp APIResponse
2680         err = json.Unmarshal(res.body, &apiResp)
2681         if err != nil {
2682                 t.Fatalf("Error unmarshaling API response: %v", err)
2683         }
2684         if got, want := apiResp.Status, "Success"; got != want {
2685                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2686         }
2687         if got, want := apiResp.Code, 200; got != want {
2688                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2689         }
2690 }
2691
2692 // TestH2APIBackendconfigBadMethod exercise backendconfig API endpoint
2693 // routine with bad method.
2694 func TestH2APIBackendconfigBadMethod(t *testing.T) {
2695         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
2696                 t.Fatalf("request should not be forwarded")
2697         }, 3010)
2698         defer st.Close()
2699
2700         res, err := st.http2(requestParam{
2701                 name:   "TestH2APIBackendconfigBadMethod",
2702                 path:   "/api/v1beta1/backendconfig",
2703                 method: "GET",
2704                 body: []byte(`# comment
2705 backend=127.0.0.1,3011
2706
2707 `),
2708         })
2709         if err != nil {
2710                 t.Fatalf("Error st.http2() = %v", err)
2711         }
2712         if got, want := res.status, 405; got != want {
2713                 t.Errorf("res.status: %v; want %v", got, want)
2714         }
2715
2716         var apiResp APIResponse
2717         err = json.Unmarshal(res.body, &apiResp)
2718         if err != nil {
2719                 t.Fatalf("Error unmarshaling API response: %v", err)
2720         }
2721         if got, want := apiResp.Status, "Failure"; got != want {
2722                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2723         }
2724         if got, want := apiResp.Code, 405; got != want {
2725                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2726         }
2727 }
2728
2729 // TestH2APIConfigrevision tests configrevision API.
2730 func TestH2APIConfigrevision(t *testing.T) {
2731         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
2732                 t.Fatalf("request should not be forwarded")
2733         }, 3010)
2734         defer st.Close()
2735
2736         res, err := st.http2(requestParam{
2737                 name:   "TestH2APIConfigrevision",
2738                 path:   "/api/v1beta1/configrevision",
2739                 method: "GET",
2740         })
2741         if err != nil {
2742                 t.Fatalf("Error st.http2() = %v", err)
2743         }
2744         if got, want := res.status, 200; got != want {
2745                 t.Errorf("res.status: %v; want = %v", got, want)
2746         }
2747
2748         var apiResp APIResponse
2749         d := json.NewDecoder(bytes.NewBuffer(res.body))
2750         d.UseNumber()
2751         err = d.Decode(&apiResp)
2752         if err != nil {
2753                 t.Fatalf("Error unmarshalling API response: %v", err)
2754         }
2755         if got, want := apiResp.Status, "Success"; got != want {
2756                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2757         }
2758         if got, want := apiResp.Code, 200; got != want {
2759                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2760         }
2761         if got, want := apiResp.Data["configRevision"], json.Number("0"); got != want {
2762                 t.Errorf(`apiResp.Data["configRevision"]: %v %t; want %v`, got, got, want)
2763         }
2764 }
2765
2766 // TestH2APINotFound exercise backendconfig API endpoint routine when
2767 // API endpoint is not found.
2768 func TestH2APINotFound(t *testing.T) {
2769         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
2770                 t.Fatalf("request should not be forwarded")
2771         }, 3010)
2772         defer st.Close()
2773
2774         res, err := st.http2(requestParam{
2775                 name:   "TestH2APINotFound",
2776                 path:   "/api/notfound",
2777                 method: "GET",
2778                 body: []byte(`# comment
2779 backend=127.0.0.1,3011
2780
2781 `),
2782         })
2783         if err != nil {
2784                 t.Fatalf("Error st.http2() = %v", err)
2785         }
2786         if got, want := res.status, 404; got != want {
2787                 t.Errorf("res.status: %v; want %v", got, want)
2788         }
2789
2790         var apiResp APIResponse
2791         err = json.Unmarshal(res.body, &apiResp)
2792         if err != nil {
2793                 t.Fatalf("Error unmarshaling API response: %v", err)
2794         }
2795         if got, want := apiResp.Status, "Failure"; got != want {
2796                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2797         }
2798         if got, want := apiResp.Code, 404; got != want {
2799                 t.Errorf("apiResp.Status: %v; want %v", got, want)
2800         }
2801 }
2802
2803 // TestH2Healthmon tests health monitor endpoint.
2804 func TestH2Healthmon(t *testing.T) {
2805         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
2806                 t.Fatalf("request should not be forwarded")
2807         }, 3011)
2808         defer st.Close()
2809
2810         res, err := st.http2(requestParam{
2811                 name: "TestH2Healthmon",
2812                 path: "/alpha/bravo",
2813         })
2814         if err != nil {
2815                 t.Fatalf("Error st.http2() = %v", err)
2816         }
2817         if got, want := res.status, 200; got != want {
2818                 t.Errorf("res.status: %v; want %v", got, want)
2819         }
2820 }
2821
2822 // TestH2ResponseBeforeRequestEnd tests the situation where response
2823 // ends before request body finishes.
2824 func TestH2ResponseBeforeRequestEnd(t *testing.T) {
2825         st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
2826                 t.Fatal("request should not be forwarded")
2827         })
2828         defer st.Close()
2829
2830         res, err := st.http2(requestParam{
2831                 name:        "TestH2ResponseBeforeRequestEnd",
2832                 noEndStream: true,
2833         })
2834         if err != nil {
2835                 t.Fatalf("Error st.http2() = %v", err)
2836         }
2837         if got, want := res.status, 404; got != want {
2838                 t.Errorf("res.status: %v; want %v", got, want)
2839         }
2840 }