Imported Upstream version 1.46.0
[platform/upstream/nghttp2.git] / integration-tests / nghttpx_http1_test.go
1 package nghttp2
2
3 import (
4         "bufio"
5         "bytes"
6         "encoding/json"
7         "fmt"
8         "golang.org/x/net/http2/hpack"
9         "golang.org/x/net/websocket"
10         "io"
11         "net/http"
12         "regexp"
13         "syscall"
14         "testing"
15         "time"
16 )
17
18 // TestH1H1PlainGET tests whether simple HTTP/1 GET request works.
19 func TestH1H1PlainGET(t *testing.T) {
20         st := newServerTester(nil, t, noopHandler)
21         defer st.Close()
22
23         res, err := st.http1(requestParam{
24                 name: "TestH1H1PlainGET",
25         })
26         if err != nil {
27                 t.Fatalf("Error st.http1() = %v", err)
28         }
29
30         want := 200
31         if got := res.status; got != want {
32                 t.Errorf("status = %v; want %v", got, want)
33         }
34 }
35
36 // TestH1H1PlainGETClose tests whether simple HTTP/1 GET request with
37 // Connetion: close request header field works.
38 func TestH1H1PlainGETClose(t *testing.T) {
39         st := newServerTester(nil, t, noopHandler)
40         defer st.Close()
41
42         res, err := st.http1(requestParam{
43                 name: "TestH1H1PlainGETClose",
44                 header: []hpack.HeaderField{
45                         pair("Connection", "close"),
46                 },
47         })
48         if err != nil {
49                 t.Fatalf("Error st.http1() = %v", err)
50         }
51
52         want := 200
53         if got := res.status; got != want {
54                 t.Errorf("status = %v; want %v", got, want)
55         }
56 }
57
58 // TestH1H1InvalidMethod tests that server rejects invalid method with
59 // 501 status code
60 func TestH1H1InvalidMethod(t *testing.T) {
61         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
62                 t.Errorf("server should not forward this request")
63         })
64         defer st.Close()
65
66         res, err := st.http1(requestParam{
67                 name:   "TestH1H1InvalidMethod",
68                 method: "get",
69         })
70         if err != nil {
71                 t.Fatalf("Error st.http1() = %v", err)
72         }
73
74         if got, want := res.status, 501; got != want {
75                 t.Errorf("status = %v; want %v", got, want)
76         }
77 }
78
79 // TestH1H1MultipleRequestCL tests that server rejects request which
80 // contains multiple Content-Length header fields.
81 func TestH1H1MultipleRequestCL(t *testing.T) {
82         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
83                 t.Errorf("server should not forward bad request")
84         })
85         defer st.Close()
86
87         if _, err := io.WriteString(st.conn, fmt.Sprintf(`GET / HTTP/1.1
88 Host: %v
89 Test-Case: TestH1H1MultipleRequestCL
90 Content-Length: 0
91 Content-Length: 0
92
93 `, st.authority)); err != nil {
94                 t.Fatalf("Error io.WriteString() = %v", err)
95         }
96
97         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
98         if err != nil {
99                 t.Fatalf("Error http.ReadResponse() = %v", err)
100         }
101
102         want := 400
103         if got := resp.StatusCode; got != want {
104                 t.Errorf("status: %v; want %v", got, want)
105         }
106 }
107
108 // // TestH1H1ConnectFailure tests that server handles the situation that
109 // // connection attempt to HTTP/1 backend failed.
110 // func TestH1H1ConnectFailure(t *testing.T) {
111 //      st := newServerTester(nil, t, noopHandler)
112 //      defer st.Close()
113
114 //      // shutdown backend server to simulate backend connect failure
115 //      st.ts.Close()
116
117 //      res, err := st.http1(requestParam{
118 //              name: "TestH1H1ConnectFailure",
119 //      })
120 //      if err != nil {
121 //              t.Fatalf("Error st.http1() = %v", err)
122 //      }
123 //      want := 503
124 //      if got := res.status; got != want {
125 //              t.Errorf("status: %v; want %v", got, want)
126 //      }
127 // }
128
129 // TestH1H1AffinityCookie tests that affinity cookie is sent back in
130 // cleartext http.
131 func TestH1H1AffinityCookie(t *testing.T) {
132         st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler)
133         defer st.Close()
134
135         res, err := st.http1(requestParam{
136                 name: "TestH1H1AffinityCookie",
137         })
138         if err != nil {
139                 t.Fatalf("Error st.http1() = %v", err)
140         }
141
142         if got, want := res.status, 200; got != want {
143                 t.Errorf("status = %v; want %v", got, want)
144         }
145
146         const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
147         validCookie := regexp.MustCompile(pattern)
148         if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
149                 t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
150         }
151 }
152
153 // TestH1H1AffinityCookieTLS tests that affinity cookie is sent back
154 // in https.
155 func TestH1H1AffinityCookieTLS(t *testing.T) {
156         st := newServerTesterTLS([]string{"--alpn-h1", "--affinity-cookie"}, t, noopHandler)
157         defer st.Close()
158
159         res, err := st.http1(requestParam{
160                 name: "TestH1H1AffinityCookieTLS",
161         })
162         if err != nil {
163                 t.Fatalf("Error st.http1() = %v", err)
164         }
165
166         if got, want := res.status, 200; got != want {
167                 t.Errorf("status = %v; want %v", got, want)
168         }
169
170         const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
171         validCookie := regexp.MustCompile(pattern)
172         if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
173                 t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
174         }
175 }
176
177 // TestH1H1GracefulShutdown tests graceful shutdown.
178 func TestH1H1GracefulShutdown(t *testing.T) {
179         st := newServerTester(nil, t, noopHandler)
180         defer st.Close()
181
182         res, err := st.http1(requestParam{
183                 name: "TestH1H1GracefulShutdown-1",
184         })
185         if err != nil {
186                 t.Fatalf("Error st.http1() = %v", err)
187         }
188
189         if got, want := res.status, 200; got != want {
190                 t.Errorf("status: %v; want %v", got, want)
191         }
192
193         st.cmd.Process.Signal(syscall.SIGQUIT)
194         time.Sleep(150 * time.Millisecond)
195
196         res, err = st.http1(requestParam{
197                 name: "TestH1H1GracefulShutdown-2",
198         })
199         if err != nil {
200                 t.Fatalf("Error st.http1() = %v", err)
201         }
202
203         if got, want := res.status, 200; got != want {
204                 t.Errorf("status: %v; want %v", got, want)
205         }
206
207         if got, want := res.connClose, true; got != want {
208                 t.Errorf("res.connClose: %v; want %v", got, want)
209         }
210
211         want := io.EOF
212         b := make([]byte, 256)
213         if _, err := st.conn.Read(b); err == nil || err != want {
214                 t.Errorf("st.conn.Read(): %v; want %v", err, want)
215         }
216 }
217
218 // TestH1H1HostRewrite tests that server rewrites Host header field
219 func TestH1H1HostRewrite(t *testing.T) {
220         st := newServerTester([]string{"--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
221                 w.Header().Add("request-host", r.Host)
222         })
223         defer st.Close()
224
225         res, err := st.http1(requestParam{
226                 name: "TestH1H1HostRewrite",
227         })
228         if err != nil {
229                 t.Fatalf("Error st.http1() = %v", err)
230         }
231         if got, want := res.status, 200; got != want {
232                 t.Errorf("status: %v; want %v", got, want)
233         }
234         if got, want := res.header.Get("request-host"), st.backendHost; got != want {
235                 t.Errorf("request-host: %v; want %v", got, want)
236         }
237 }
238
239 // TestH1H1BadHost tests that server rejects request including bad
240 // characters in host header field.
241 func TestH1H1BadHost(t *testing.T) {
242         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
243                 t.Errorf("server should not forward this request")
244         })
245         defer st.Close()
246
247         if _, err := io.WriteString(st.conn, "GET / HTTP/1.1\r\nTest-Case: TestH1H1HBadHost\r\nHost: foo\"bar\r\n\r\n"); err != nil {
248                 t.Fatalf("Error io.WriteString() = %v", err)
249         }
250         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
251         if err != nil {
252                 t.Fatalf("Error http.ReadResponse() = %v", err)
253         }
254         if got, want := resp.StatusCode, 400; got != want {
255                 t.Errorf("status: %v; want %v", got, want)
256         }
257 }
258
259 // TestH1H1BadAuthority tests that server rejects request including
260 // bad characters in authority component of requset URI.
261 func TestH1H1BadAuthority(t *testing.T) {
262         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
263                 t.Errorf("server should not forward this request")
264         })
265         defer st.Close()
266
267         if _, err := io.WriteString(st.conn, "GET http://foo\"bar/ HTTP/1.1\r\nTest-Case: TestH1H1HBadAuthority\r\nHost: foobar\r\n\r\n"); err != nil {
268                 t.Fatalf("Error io.WriteString() = %v", err)
269         }
270         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
271         if err != nil {
272                 t.Fatalf("Error http.ReadResponse() = %v", err)
273         }
274         if got, want := resp.StatusCode, 400; got != want {
275                 t.Errorf("status: %v; want %v", got, want)
276         }
277 }
278
279 // TestH1H1BadScheme tests that server rejects request including
280 // bad characters in scheme component of requset URI.
281 func TestH1H1BadScheme(t *testing.T) {
282         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
283                 t.Errorf("server should not forward this request")
284         })
285         defer st.Close()
286
287         if _, err := io.WriteString(st.conn, "GET http*://example.com/ HTTP/1.1\r\nTest-Case: TestH1H1HBadScheme\r\nHost: example.com\r\n\r\n"); err != nil {
288                 t.Fatalf("Error io.WriteString() = %v", err)
289         }
290         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
291         if err != nil {
292                 t.Fatalf("Error http.ReadResponse() = %v", err)
293         }
294         if got, want := resp.StatusCode, 400; got != want {
295                 t.Errorf("status: %v; want %v", got, want)
296         }
297 }
298
299 // TestH1H1HTTP10 tests that server can accept HTTP/1.0 request
300 // without Host header field
301 func TestH1H1HTTP10(t *testing.T) {
302         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
303                 w.Header().Add("request-host", r.Host)
304         })
305         defer st.Close()
306
307         if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1HTTP10\r\n\r\n"); err != nil {
308                 t.Fatalf("Error io.WriteString() = %v", err)
309         }
310
311         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
312         if err != nil {
313                 t.Fatalf("Error http.ReadResponse() = %v", err)
314         }
315
316         if got, want := resp.StatusCode, 200; got != want {
317                 t.Errorf("status: %v; want %v", got, want)
318         }
319         if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
320                 t.Errorf("request-host: %v; want %v", got, want)
321         }
322 }
323
324 // TestH1H1HTTP10NoHostRewrite tests that server generates host header
325 // field using actual backend server even if --no-http-rewrite is
326 // used.
327 func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
328         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
329                 w.Header().Add("request-host", r.Host)
330         })
331         defer st.Close()
332
333         if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1HTTP10NoHostRewrite\r\n\r\n"); err != nil {
334                 t.Fatalf("Error io.WriteString() = %v", err)
335         }
336
337         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
338         if err != nil {
339                 t.Fatalf("Error http.ReadResponse() = %v", err)
340         }
341
342         if got, want := resp.StatusCode, 200; got != want {
343                 t.Errorf("status: %v; want %v", got, want)
344         }
345         if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
346                 t.Errorf("request-host: %v; want %v", got, want)
347         }
348 }
349
350 // TestH1H1RequestTrailer tests request trailer part is forwarded to
351 // backend.
352 func TestH1H1RequestTrailer(t *testing.T) {
353         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
354                 buf := make([]byte, 4096)
355                 for {
356                         _, err := r.Body.Read(buf)
357                         if err == io.EOF {
358                                 break
359                         }
360                         if err != nil {
361                                 t.Fatalf("r.Body.Read() = %v", err)
362                         }
363                 }
364                 if got, want := r.Trailer.Get("foo"), "bar"; got != want {
365                         t.Errorf("r.Trailer.Get(foo): %v; want %v", got, want)
366                 }
367         })
368         defer st.Close()
369
370         res, err := st.http1(requestParam{
371                 name: "TestH1H1RequestTrailer",
372                 body: []byte("1"),
373                 trailer: []hpack.HeaderField{
374                         pair("foo", "bar"),
375                 },
376         })
377         if err != nil {
378                 t.Fatalf("Error st.http1() = %v", err)
379         }
380         if got, want := res.status, 200; got != want {
381                 t.Errorf("res.status: %v; want %v", got, want)
382         }
383 }
384
385 // TestH1H1HeaderFieldBufferPath tests that request with request path
386 // larger than configured buffer size is rejected.
387 func TestH1H1HeaderFieldBufferPath(t *testing.T) {
388         // The value 100 is chosen so that sum of header fields bytes
389         // does not exceed it.  We use > 100 bytes URI to exceed this
390         // limit.
391         st := newServerTester([]string{"--request-header-field-buffer=100"}, t, func(w http.ResponseWriter, r *http.Request) {
392                 t.Fatal("execution path should not be here")
393         })
394         defer st.Close()
395
396         res, err := st.http1(requestParam{
397                 name: "TestH1H1HeaderFieldBufferPath",
398                 path: "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
399         })
400         if err != nil {
401                 t.Fatalf("Error st.http1() = %v", err)
402         }
403         if got, want := res.status, 431; got != want {
404                 t.Errorf("status: %v; want %v", got, want)
405         }
406 }
407
408 // TestH1H1HeaderFieldBuffer tests that request with header fields
409 // larger than configured buffer size is rejected.
410 func TestH1H1HeaderFieldBuffer(t *testing.T) {
411         st := newServerTester([]string{"--request-header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
412                 t.Fatal("execution path should not be here")
413         })
414         defer st.Close()
415
416         res, err := st.http1(requestParam{
417                 name: "TestH1H1HeaderFieldBuffer",
418         })
419         if err != nil {
420                 t.Fatalf("Error st.http1() = %v", err)
421         }
422         if got, want := res.status, 431; got != want {
423                 t.Errorf("status: %v; want %v", got, want)
424         }
425 }
426
427 // TestH1H1HeaderFields tests that request with header fields more
428 // than configured number is rejected.
429 func TestH1H1HeaderFields(t *testing.T) {
430         st := newServerTester([]string{"--max-request-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
431                 t.Fatal("execution path should not be here")
432         })
433         defer st.Close()
434
435         res, err := st.http1(requestParam{
436                 name: "TestH1H1HeaderFields",
437                 header: []hpack.HeaderField{
438                         // Add extra header field to ensure that
439                         // header field limit exceeds
440                         pair("Connection", "close"),
441                 },
442         })
443         if err != nil {
444                 t.Fatalf("Error st.http1() = %v", err)
445         }
446         if got, want := res.status, 431; got != want {
447                 t.Errorf("status: %v; want %v", got, want)
448         }
449 }
450
451 // TestH1H1Websocket tests that HTTP Upgrade to WebSocket works.
452 func TestH1H1Websocket(t *testing.T) {
453         st := newServerTesterHandler(nil, t, websocket.Handler(func(ws *websocket.Conn) {
454                 io.Copy(ws, ws)
455         }))
456         defer st.Close()
457
458         content := []byte("hello world")
459         res, err := st.websocket(requestParam{
460                 name: "TestH1H1Websocket",
461                 body: content,
462         })
463         if err != nil {
464                 t.Fatalf("Error st.websocket() = %v", err)
465         }
466         if got, want := res.body, content; !bytes.Equal(got, want) {
467                 t.Errorf("echo: %q; want %q", got, want)
468         }
469 }
470
471 // TestH1H1ReqPhaseSetHeader tests mruby request phase hook
472 // modifies request header fields.
473 func TestH1H1ReqPhaseSetHeader(t *testing.T) {
474         st := newServerTester([]string{"--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
475                 if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
476                         t.Errorf("User-Agent = %v; want %v", got, want)
477                 }
478         })
479         defer st.Close()
480
481         res, err := st.http1(requestParam{
482                 name: "TestH1H1ReqPhaseSetHeader",
483         })
484         if err != nil {
485                 t.Fatalf("Error st.http1() = %v", err)
486         }
487
488         if got, want := res.status, 200; got != want {
489                 t.Errorf("status = %v; want %v", got, want)
490         }
491 }
492
493 // TestH1H1ReqPhaseReturn tests mruby request phase hook returns
494 // custom response.
495 func TestH1H1ReqPhaseReturn(t *testing.T) {
496         st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
497                 t.Fatalf("request should not be forwarded")
498         })
499         defer st.Close()
500
501         res, err := st.http1(requestParam{
502                 name: "TestH1H1ReqPhaseReturn",
503         })
504         if err != nil {
505                 t.Fatalf("Error st.http1() = %v", err)
506         }
507
508         if got, want := res.status, 404; got != want {
509                 t.Errorf("status = %v; want %v", got, want)
510         }
511
512         hdtests := []struct {
513                 k, v string
514         }{
515                 {"content-length", "20"},
516                 {"from", "mruby"},
517         }
518         for _, tt := range hdtests {
519                 if got, want := res.header.Get(tt.k), tt.v; got != want {
520                         t.Errorf("%v = %v; want %v", tt.k, got, want)
521                 }
522         }
523
524         if got, want := string(res.body), "Hello World from req"; got != want {
525                 t.Errorf("body = %v; want %v", got, want)
526         }
527 }
528
529 // TestH1H1RespPhaseSetHeader tests mruby response phase hook modifies
530 // response header fields.
531 func TestH1H1RespPhaseSetHeader(t *testing.T) {
532         st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
533         defer st.Close()
534
535         res, err := st.http1(requestParam{
536                 name: "TestH1H1RespPhaseSetHeader",
537         })
538         if err != nil {
539                 t.Fatalf("Error st.http1() = %v", err)
540         }
541
542         if got, want := res.status, 200; got != want {
543                 t.Errorf("status = %v; want %v", got, want)
544         }
545
546         if got, want := res.header.Get("alpha"), "bravo"; got != want {
547                 t.Errorf("alpha = %v; want %v", got, want)
548         }
549 }
550
551 // TestH1H1RespPhaseReturn tests mruby response phase hook returns
552 // custom response.
553 func TestH1H1RespPhaseReturn(t *testing.T) {
554         st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
555         defer st.Close()
556
557         res, err := st.http1(requestParam{
558                 name: "TestH1H1RespPhaseReturn",
559         })
560         if err != nil {
561                 t.Fatalf("Error st.http1() = %v", err)
562         }
563
564         if got, want := res.status, 404; got != want {
565                 t.Errorf("status = %v; want %v", got, want)
566         }
567
568         hdtests := []struct {
569                 k, v string
570         }{
571                 {"content-length", "21"},
572                 {"from", "mruby"},
573         }
574         for _, tt := range hdtests {
575                 if got, want := res.header.Get(tt.k), tt.v; got != want {
576                         t.Errorf("%v = %v; want %v", tt.k, got, want)
577                 }
578         }
579
580         if got, want := string(res.body), "Hello World from resp"; got != want {
581                 t.Errorf("body = %v; want %v", got, want)
582         }
583 }
584
585 // TestH1H1HTTPSRedirect tests that the request to the backend which
586 // requires TLS is redirected to https URI.
587 func TestH1H1HTTPSRedirect(t *testing.T) {
588         st := newServerTester([]string{"--redirect-if-not-tls"}, t, noopHandler)
589         defer st.Close()
590
591         res, err := st.http1(requestParam{
592                 name: "TestH1H1HTTPSRedirect",
593         })
594         if err != nil {
595                 t.Fatalf("Error st.http1() = %v", err)
596         }
597
598         if got, want := res.status, 308; got != want {
599                 t.Errorf("status = %v; want %v", got, want)
600         }
601         if got, want := res.header.Get("location"), "https://127.0.0.1/"; got != want {
602                 t.Errorf("location: %v; want %v", got, want)
603         }
604 }
605
606 // TestH1H1HTTPSRedirectPort tests that the request to the backend
607 // which requires TLS is redirected to https URI with given port.
608 func TestH1H1HTTPSRedirectPort(t *testing.T) {
609         st := newServerTester([]string{"--redirect-if-not-tls", "--redirect-https-port=8443"}, t, noopHandler)
610         defer st.Close()
611
612         res, err := st.http1(requestParam{
613                 path: "/foo?bar",
614                 name: "TestH1H1HTTPSRedirectPort",
615         })
616         if err != nil {
617                 t.Fatalf("Error st.http1() = %v", err)
618         }
619
620         if got, want := res.status, 308; got != want {
621                 t.Errorf("status = %v; want %v", got, want)
622         }
623         if got, want := res.header.Get("location"), "https://127.0.0.1:8443/foo?bar"; got != want {
624                 t.Errorf("location: %v; want %v", got, want)
625         }
626 }
627
628 // TestH1H1POSTRequests tests that server can handle 2 requests with
629 // request body.
630 func TestH1H1POSTRequests(t *testing.T) {
631         st := newServerTester(nil, t, noopHandler)
632         defer st.Close()
633
634         res, err := st.http1(requestParam{
635                 name: "TestH1H1POSTRequestsNo1",
636                 body: make([]byte, 1),
637         })
638         if err != nil {
639                 t.Fatalf("Error st.http1() = %v", err)
640         }
641         if got, want := res.status, 200; got != want {
642                 t.Errorf("res.status: %v; want %v", got, want)
643         }
644
645         res, err = st.http1(requestParam{
646                 name: "TestH1H1POSTRequestsNo2",
647                 body: make([]byte, 65536),
648         })
649         if err != nil {
650                 t.Fatalf("Error st.http1() = %v", err)
651         }
652         if got, want := res.status, 200; got != want {
653                 t.Errorf("res.status: %v; want %v", got, want)
654         }
655 }
656
657 // // TestH1H2ConnectFailure tests that server handles the situation that
658 // // connection attempt to HTTP/2 backend failed.
659 // func TestH1H2ConnectFailure(t *testing.T) {
660 //      st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
661 //      defer st.Close()
662
663 //      // simulate backend connect attempt failure
664 //      st.ts.Close()
665
666 //      res, err := st.http1(requestParam{
667 //              name: "TestH1H2ConnectFailure",
668 //      })
669 //      if err != nil {
670 //              t.Fatalf("Error st.http1() = %v", err)
671 //      }
672 //      want := 503
673 //      if got := res.status; got != want {
674 //              t.Errorf("status: %v; want %v", got, want)
675 //      }
676 // }
677
678 // TestH1H2NoHost tests that server rejects request without Host
679 // header field for HTTP/2 backend.
680 func TestH1H2NoHost(t *testing.T) {
681         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
682                 t.Errorf("server should not forward bad request")
683         })
684         defer st.Close()
685
686         // without Host header field, we expect 400 response
687         if _, err := io.WriteString(st.conn, "GET / HTTP/1.1\r\nTest-Case: TestH1H2NoHost\r\n\r\n"); err != nil {
688                 t.Fatalf("Error io.WriteString() = %v", err)
689         }
690
691         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
692         if err != nil {
693                 t.Fatalf("Error http.ReadResponse() = %v", err)
694         }
695
696         want := 400
697         if got := resp.StatusCode; got != want {
698                 t.Errorf("status: %v; want %v", got, want)
699         }
700 }
701
702 // TestH1H2HTTP10 tests that server can accept HTTP/1.0 request
703 // without Host header field
704 func TestH1H2HTTP10(t *testing.T) {
705         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
706                 w.Header().Add("request-host", r.Host)
707         })
708         defer st.Close()
709
710         if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H2HTTP10\r\n\r\n"); err != nil {
711                 t.Fatalf("Error io.WriteString() = %v", err)
712         }
713
714         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
715         if err != nil {
716                 t.Fatalf("Error http.ReadResponse() = %v", err)
717         }
718
719         if got, want := resp.StatusCode, 200; got != want {
720                 t.Errorf("status: %v; want %v", got, want)
721         }
722         if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
723                 t.Errorf("request-host: %v; want %v", got, want)
724         }
725 }
726
727 // TestH1H2HTTP10NoHostRewrite tests that server generates host header
728 // field using actual backend server even if --no-http-rewrite is
729 // used.
730 func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
731         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
732                 w.Header().Add("request-host", r.Host)
733         })
734         defer st.Close()
735
736         if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H2HTTP10NoHostRewrite\r\n\r\n"); err != nil {
737                 t.Fatalf("Error io.WriteString() = %v", err)
738         }
739
740         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
741         if err != nil {
742                 t.Fatalf("Error http.ReadResponse() = %v", err)
743         }
744
745         if got, want := resp.StatusCode, 200; got != want {
746                 t.Errorf("status: %v; want %v", got, want)
747         }
748         if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
749                 t.Errorf("request-host: %v; want %v", got, want)
750         }
751 }
752
753 // TestH1H2CrumbleCookie tests that Cookies are crumbled and assembled
754 // when forwarding to HTTP/2 backend link.  go-nghttp2 server
755 // concatenates crumbled Cookies automatically, so this test is not
756 // much effective now.
757 func TestH1H2CrumbleCookie(t *testing.T) {
758         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
759                 if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
760                         t.Errorf("Cookie: %v; want %v", got, want)
761                 }
762         })
763         defer st.Close()
764
765         res, err := st.http1(requestParam{
766                 name: "TestH1H2CrumbleCookie",
767                 header: []hpack.HeaderField{
768                         pair("Cookie", "alpha; bravo; charlie"),
769                 },
770         })
771         if err != nil {
772                 t.Fatalf("Error st.http1() = %v", err)
773         }
774         if got, want := res.status, 200; got != want {
775                 t.Errorf("status: %v; want %v", got, want)
776         }
777 }
778
779 // TestH1H2GenerateVia tests that server generates Via header field to and
780 // from backend server.
781 func TestH1H2GenerateVia(t *testing.T) {
782         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
783                 if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
784                         t.Errorf("Via: %v; want %v", got, want)
785                 }
786         })
787         defer st.Close()
788
789         res, err := st.http1(requestParam{
790                 name: "TestH1H2GenerateVia",
791         })
792         if err != nil {
793                 t.Fatalf("Error st.http1() = %v", err)
794         }
795         if got, want := res.header.Get("Via"), "2 nghttpx"; got != want {
796                 t.Errorf("Via: %v; want %v", got, want)
797         }
798 }
799
800 // TestH1H2AppendVia tests that server adds value to existing Via
801 // header field to and from backend server.
802 func TestH1H2AppendVia(t *testing.T) {
803         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
804                 if got, want := r.Header.Get("Via"), "foo, 1.1 nghttpx"; got != want {
805                         t.Errorf("Via: %v; want %v", got, want)
806                 }
807                 w.Header().Add("Via", "bar")
808         })
809         defer st.Close()
810
811         res, err := st.http1(requestParam{
812                 name: "TestH1H2AppendVia",
813                 header: []hpack.HeaderField{
814                         pair("via", "foo"),
815                 },
816         })
817         if err != nil {
818                 t.Fatalf("Error st.http1() = %v", err)
819         }
820         if got, want := res.header.Get("Via"), "bar, 2 nghttpx"; got != want {
821                 t.Errorf("Via: %v; want %v", got, want)
822         }
823 }
824
825 // TestH1H2NoVia tests that server does not add value to existing Via
826 // header field to and from backend server.
827 func TestH1H2NoVia(t *testing.T) {
828         st := newServerTester([]string{"--http2-bridge", "--no-via"}, t, func(w http.ResponseWriter, r *http.Request) {
829                 if got, want := r.Header.Get("Via"), "foo"; got != want {
830                         t.Errorf("Via: %v; want %v", got, want)
831                 }
832                 w.Header().Add("Via", "bar")
833         })
834         defer st.Close()
835
836         res, err := st.http1(requestParam{
837                 name: "TestH1H2NoVia",
838                 header: []hpack.HeaderField{
839                         pair("via", "foo"),
840                 },
841         })
842         if err != nil {
843                 t.Fatalf("Error st.http1() = %v", err)
844         }
845         if got, want := res.header.Get("Via"), "bar"; got != want {
846                 t.Errorf("Via: %v; want %v", got, want)
847         }
848 }
849
850 // TestH1H2ReqPhaseReturn tests mruby request phase hook returns
851 // custom response.
852 func TestH1H2ReqPhaseReturn(t *testing.T) {
853         st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
854                 t.Fatalf("request should not be forwarded")
855         })
856         defer st.Close()
857
858         res, err := st.http1(requestParam{
859                 name: "TestH1H2ReqPhaseReturn",
860         })
861         if err != nil {
862                 t.Fatalf("Error st.http1() = %v", err)
863         }
864
865         if got, want := res.status, 404; got != want {
866                 t.Errorf("status = %v; want %v", got, want)
867         }
868
869         hdtests := []struct {
870                 k, v string
871         }{
872                 {"content-length", "20"},
873                 {"from", "mruby"},
874         }
875         for _, tt := range hdtests {
876                 if got, want := res.header.Get(tt.k), tt.v; got != want {
877                         t.Errorf("%v = %v; want %v", tt.k, got, want)
878                 }
879         }
880
881         if got, want := string(res.body), "Hello World from req"; got != want {
882                 t.Errorf("body = %v; want %v", got, want)
883         }
884 }
885
886 // TestH1H2RespPhaseReturn tests mruby response phase hook returns
887 // custom response.
888 func TestH1H2RespPhaseReturn(t *testing.T) {
889         st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
890         defer st.Close()
891
892         res, err := st.http1(requestParam{
893                 name: "TestH1H2RespPhaseReturn",
894         })
895         if err != nil {
896                 t.Fatalf("Error st.http1() = %v", err)
897         }
898
899         if got, want := res.status, 404; got != want {
900                 t.Errorf("status = %v; want %v", got, want)
901         }
902
903         hdtests := []struct {
904                 k, v string
905         }{
906                 {"content-length", "21"},
907                 {"from", "mruby"},
908         }
909         for _, tt := range hdtests {
910                 if got, want := res.header.Get(tt.k), tt.v; got != want {
911                         t.Errorf("%v = %v; want %v", tt.k, got, want)
912                 }
913         }
914
915         if got, want := string(res.body), "Hello World from resp"; got != want {
916                 t.Errorf("body = %v; want %v", got, want)
917         }
918 }
919
920 // TestH1H2TE tests that "te: trailers" header is forwarded to HTTP/2
921 // backend server by stripping other encodings.
922 func TestH1H2TE(t *testing.T) {
923         st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
924                 if got, want := r.Header.Get("te"), "trailers"; got != want {
925                         t.Errorf("te: %v; want %v", got, want)
926                 }
927         })
928         defer st.Close()
929
930         res, err := st.http1(requestParam{
931                 name: "TestH1H2TE",
932                 header: []hpack.HeaderField{
933                         pair("te", "foo,trailers,bar"),
934                 },
935         })
936         if err != nil {
937                 t.Fatalf("Error st.http1() = %v", err)
938         }
939         if got, want := res.status, 200; got != want {
940                 t.Errorf("status: %v; want %v", got, want)
941         }
942 }
943
944 // TestH1APIBackendconfig exercise backendconfig API endpoint routine
945 // for successful case.
946 func TestH1APIBackendconfig(t *testing.T) {
947         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
948                 t.Fatalf("request should not be forwarded")
949         }, 3010)
950         defer st.Close()
951
952         res, err := st.http1(requestParam{
953                 name:   "TestH1APIBackendconfig",
954                 path:   "/api/v1beta1/backendconfig",
955                 method: "PUT",
956                 body: []byte(`# comment
957 backend=127.0.0.1,3011
958
959 `),
960         })
961         if err != nil {
962                 t.Fatalf("Error st.http1() = %v", err)
963         }
964         if got, want := res.status, 200; got != want {
965                 t.Errorf("res.status: %v; want %v", got, want)
966         }
967
968         var apiResp APIResponse
969         err = json.Unmarshal(res.body, &apiResp)
970         if err != nil {
971                 t.Fatalf("Error unmarshaling API response: %v", err)
972         }
973         if got, want := apiResp.Status, "Success"; got != want {
974                 t.Errorf("apiResp.Status: %v; want %v", got, want)
975         }
976         if got, want := apiResp.Code, 200; got != want {
977                 t.Errorf("apiResp.Status: %v; want %v", got, want)
978         }
979 }
980
981 // TestH1APIBackendconfigQuery exercise backendconfig API endpoint
982 // routine with query.
983 func TestH1APIBackendconfigQuery(t *testing.T) {
984         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
985                 t.Fatalf("request should not be forwarded")
986         }, 3010)
987         defer st.Close()
988
989         res, err := st.http1(requestParam{
990                 name:   "TestH1APIBackendconfigQuery",
991                 path:   "/api/v1beta1/backendconfig?foo=bar",
992                 method: "PUT",
993                 body: []byte(`# comment
994 backend=127.0.0.1,3011
995
996 `),
997         })
998         if err != nil {
999                 t.Fatalf("Error st.http1() = %v", err)
1000         }
1001         if got, want := res.status, 200; got != want {
1002                 t.Errorf("res.status: %v; want %v", got, want)
1003         }
1004
1005         var apiResp APIResponse
1006         err = json.Unmarshal(res.body, &apiResp)
1007         if err != nil {
1008                 t.Fatalf("Error unmarshaling API response: %v", err)
1009         }
1010         if got, want := apiResp.Status, "Success"; got != want {
1011                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1012         }
1013         if got, want := apiResp.Code, 200; got != want {
1014                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1015         }
1016 }
1017
1018 // TestH1APIBackendconfigBadMethod exercise backendconfig API endpoint
1019 // routine with bad method.
1020 func TestH1APIBackendconfigBadMethod(t *testing.T) {
1021         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
1022                 t.Fatalf("request should not be forwarded")
1023         }, 3010)
1024         defer st.Close()
1025
1026         res, err := st.http1(requestParam{
1027                 name:   "TestH1APIBackendconfigBadMethod",
1028                 path:   "/api/v1beta1/backendconfig",
1029                 method: "GET",
1030                 body: []byte(`# comment
1031 backend=127.0.0.1,3011
1032
1033 `),
1034         })
1035         if err != nil {
1036                 t.Fatalf("Error st.http1() = %v", err)
1037         }
1038         if got, want := res.status, 405; got != want {
1039                 t.Errorf("res.status: %v; want %v", got, want)
1040         }
1041
1042         var apiResp APIResponse
1043         err = json.Unmarshal(res.body, &apiResp)
1044         if err != nil {
1045                 t.Fatalf("Error unmarshaling API response: %v", err)
1046         }
1047         if got, want := apiResp.Status, "Failure"; got != want {
1048                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1049         }
1050         if got, want := apiResp.Code, 405; got != want {
1051                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1052         }
1053 }
1054
1055 // TestH1APIConfigrevision tests configrevision API.
1056 func TestH1APIConfigrevision(t *testing.T) {
1057         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
1058                 t.Fatalf("request should not be forwarded")
1059         }, 3010)
1060         defer st.Close()
1061
1062         res, err := st.http1(requestParam{
1063                 name:   "TestH1APIConfigrevision",
1064                 path:   "/api/v1beta1/configrevision",
1065                 method: "GET",
1066         })
1067         if err != nil {
1068                 t.Fatalf("Error st.http1() = %v", err)
1069         }
1070         if got, want := res.status, 200; got != want {
1071                 t.Errorf("res.status: %v; want = %v", got, want)
1072         }
1073
1074         var apiResp APIResponse
1075         d := json.NewDecoder(bytes.NewBuffer(res.body))
1076         d.UseNumber()
1077         err = d.Decode(&apiResp)
1078         if err != nil {
1079                 t.Fatalf("Error unmarshalling API response: %v", err)
1080         }
1081         if got, want := apiResp.Status, "Success"; got != want {
1082                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1083         }
1084         if got, want := apiResp.Code, 200; got != want {
1085                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1086         }
1087         if got, want := apiResp.Data["configRevision"], json.Number("0"); got != want {
1088                 t.Errorf(`apiResp.Data["configRevision"]: %v %t; want %v`, got, got, want)
1089         }
1090 }
1091
1092 // TestH1APINotFound exercise backendconfig API endpoint routine when
1093 // API endpoint is not found.
1094 func TestH1APINotFound(t *testing.T) {
1095         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
1096                 t.Fatalf("request should not be forwarded")
1097         }, 3010)
1098         defer st.Close()
1099
1100         res, err := st.http1(requestParam{
1101                 name:   "TestH1APINotFound",
1102                 path:   "/api/notfound",
1103                 method: "GET",
1104                 body: []byte(`# comment
1105 backend=127.0.0.1,3011
1106
1107 `),
1108         })
1109         if err != nil {
1110                 t.Fatalf("Error st.http1() = %v", err)
1111         }
1112         if got, want := res.status, 404; got != want {
1113                 t.Errorf("res.status: %v; want %v", got, want)
1114         }
1115
1116         var apiResp APIResponse
1117         err = json.Unmarshal(res.body, &apiResp)
1118         if err != nil {
1119                 t.Fatalf("Error unmarshaling API response: %v", err)
1120         }
1121         if got, want := apiResp.Status, "Failure"; got != want {
1122                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1123         }
1124         if got, want := apiResp.Code, 404; got != want {
1125                 t.Errorf("apiResp.Status: %v; want %v", got, want)
1126         }
1127 }
1128
1129 // TestH1Healthmon tests health monitor endpoint.
1130 func TestH1Healthmon(t *testing.T) {
1131         st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
1132                 t.Fatalf("request should not be forwarded")
1133         }, 3011)
1134         defer st.Close()
1135
1136         res, err := st.http1(requestParam{
1137                 name: "TestH1Healthmon",
1138                 path: "/alpha/bravo",
1139         })
1140         if err != nil {
1141                 t.Fatalf("Error st.http1() = %v", err)
1142         }
1143         if got, want := res.status, 200; got != want {
1144                 t.Errorf("res.status: %v; want %v", got, want)
1145         }
1146 }
1147
1148 // TestH1ResponseBeforeRequestEnd tests the situation where response
1149 // ends before request body finishes.
1150 func TestH1ResponseBeforeRequestEnd(t *testing.T) {
1151         st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
1152                 t.Fatal("request should not be forwarded")
1153         })
1154         defer st.Close()
1155
1156         if _, err := io.WriteString(st.conn, fmt.Sprintf(`POST / HTTP/1.1
1157 Host: %v
1158 Test-Case: TestH1ResponseBeforeRequestEnd
1159 Content-Length: 1000000
1160
1161 `, st.authority)); err != nil {
1162                 t.Fatalf("Error io.WriteString() = %v", err)
1163         }
1164
1165         resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
1166         if err != nil {
1167                 t.Fatalf("Error http.ReadResponse() = %v", err)
1168         }
1169
1170         if got, want := resp.StatusCode, 404; got != want {
1171                 t.Errorf("status: %v; want %v", got, want)
1172         }
1173 }
1174
1175 // TestH1H1ChunkedEndsPrematurely tests that an HTTP/1.1 request fails
1176 // if the backend chunked encoded response ends prematurely.
1177 func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
1178         st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
1179                 hj, ok := w.(http.Hijacker)
1180                 if !ok {
1181                         http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
1182                         return
1183                 }
1184                 conn, bufrw, err := hj.Hijack()
1185                 if err != nil {
1186                         http.Error(w, err.Error(), http.StatusInternalServerError)
1187                         return
1188                 }
1189                 defer conn.Close()
1190                 bufrw.WriteString("HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\n\r\n")
1191                 bufrw.Flush()
1192         })
1193         defer st.Close()
1194
1195         _, err := st.http1(requestParam{
1196                 name: "TestH1H1ChunkedEndsPrematurely",
1197         })
1198         if err == nil {
1199                 t.Fatal("st.http1() should fail")
1200         }
1201 }