6 "github.com/bradfitz/http2/hpack"
13 // TestH1H1PlainGET tests whether simple HTTP/1 GET request works.
14 func TestH1H1PlainGET(t *testing.T) {
15 st := newServerTester(nil, t, noopHandler)
18 res, err := st.http1(requestParam{
19 name: "TestH1H1PlainGET",
22 t.Fatalf("Error st.http1() = %v", err)
26 if got := res.status; got != want {
27 t.Errorf("status = %v; want %v", got, want)
31 // TestH1H1PlainGETClose tests whether simple HTTP/1 GET request with
32 // Connetion: close request header field works.
33 func TestH1H1PlainGETClose(t *testing.T) {
34 st := newServerTester(nil, t, noopHandler)
37 res, err := st.http1(requestParam{
38 name: "TestH1H1PlainGETClose",
39 header: []hpack.HeaderField{
40 pair("Connection", "close"),
44 t.Fatalf("Error st.http1() = %v", err)
48 if got := res.status; got != want {
49 t.Errorf("status = %v; want %v", got, want)
53 // TestH1H1MultipleRequestCL tests that server rejects request which
54 // contains multiple Content-Length header fields.
55 func TestH1H1MultipleRequestCL(t *testing.T) {
56 st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
57 t.Errorf("server should not forward bad request")
61 if _, err := io.WriteString(st.conn, fmt.Sprintf(`GET / HTTP/1.1
63 Test-Case: TestH1H1MultipleRequestCL
67 `, st.authority)); err != nil {
68 t.Fatalf("Error io.WriteString() = %v", err)
71 resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
73 t.Fatalf("Error http.ReadResponse() = %v", err)
77 if got := resp.StatusCode; got != want {
78 t.Errorf("status: %v; want %v", got, want)
82 // TestH1H1ConnectFailure tests that server handles the situation that
83 // connection attempt to HTTP/1 backend failed.
84 func TestH1H1ConnectFailure(t *testing.T) {
85 st := newServerTester(nil, t, noopHandler)
88 // shutdown backend server to simulate backend connect failure
91 res, err := st.http1(requestParam{
92 name: "TestH1H1ConnectFailure",
95 t.Fatalf("Error st.http1() = %v", err)
98 if got := res.status; got != want {
99 t.Errorf("status: %v; want %v", got, want)
103 // TestH1H1GracefulShutdown tests graceful shutdown.
104 func TestH1H1GracefulShutdown(t *testing.T) {
105 st := newServerTester(nil, t, noopHandler)
108 res, err := st.http1(requestParam{
109 name: "TestH1H1GracefulShutdown-1",
112 t.Fatalf("Error st.http1() = %v", err)
115 if got, want := res.status, 200; got != want {
116 t.Errorf("status: %v; want %v", got, want)
119 st.cmd.Process.Signal(syscall.SIGQUIT)
121 res, err = st.http1(requestParam{
122 name: "TestH1H1GracefulShutdown-2",
125 t.Fatalf("Error st.http1() = %v", err)
128 if got, want := res.status, 200; got != want {
129 t.Errorf("status: %v; want %v", got, want)
132 if got, want := res.connClose, true; got != want {
133 t.Errorf("res.connClose: %v; want %v", got, want)
137 if _, err := st.conn.Read(nil); err == nil || err != want {
138 t.Errorf("st.conn.Read(): %v; want %v", err, want)
142 // TestH1H1HostRewrite tests that server rewrites Host header field
143 func TestH1H1HostRewrite(t *testing.T) {
144 st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
145 w.Header().Add("request-host", r.Host)
149 res, err := st.http1(requestParam{
150 name: "TestH1H1HostRewrite",
153 t.Fatalf("Error st.http1() = %v", err)
155 if got, want := res.status, 200; got != want {
156 t.Errorf("status: %v; want %v", got, want)
158 if got, want := res.header.Get("request-host"), st.backendHost; got != want {
159 t.Errorf("request-host: %v; want %v", got, want)
163 // TestH1H1HTTP10 tests that server can accept HTTP/1.0 request
164 // without Host header field
165 func TestH1H1HTTP10(t *testing.T) {
166 st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
167 w.Header().Add("request-host", r.Host)
171 if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1HTTP10\r\n\r\n"); err != nil {
172 t.Fatalf("Error io.WriteString() = %v", err)
175 resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
177 t.Fatalf("Error http.ReadResponse() = %v", err)
180 if got, want := resp.StatusCode, 200; got != want {
181 t.Errorf("status: %v; want %v", got, want)
183 if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
184 t.Errorf("request-host: %v; want %v", got, want)
188 // TestH1H1HTTP10NoHostRewrite tests that server generates host header
189 // field using actual backend server even if --no-http-rewrite is
191 func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
192 st := newServerTester([]string{"--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
193 w.Header().Add("request-host", r.Host)
197 if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1HTTP10NoHostRewrite\r\n\r\n"); err != nil {
198 t.Fatalf("Error io.WriteString() = %v", err)
201 resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
203 t.Fatalf("Error http.ReadResponse() = %v", err)
206 if got, want := resp.StatusCode, 200; got != want {
207 t.Errorf("status: %v; want %v", got, want)
209 if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
210 t.Errorf("request-host: %v; want %v", got, want)
214 // TestH1H1RequestTrailer tests request trailer part is forwarded to
216 func TestH1H1RequestTrailer(t *testing.T) {
217 st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
218 buf := make([]byte, 4096)
220 _, err := r.Body.Read(buf)
225 t.Fatalf("r.Body.Read() = %v", err)
228 if got, want := r.Trailer.Get("foo"), "bar"; got != want {
229 t.Errorf("r.Trailer.Get(foo): %v; want %v", got, want)
234 res, err := st.http1(requestParam{
235 name: "TestH1H1RequestTrailer",
237 trailer: []hpack.HeaderField{
242 t.Fatalf("Error st.http1() = %v", err)
244 if got, want := res.status, 200; got != want {
245 t.Errorf("res.status: %v; want %v", got, want)
249 // TestH1H1HeaderFieldBufferPath tests that request with request path
250 // larger than configured buffer size is rejected.
251 func TestH1H1HeaderFieldBufferPath(t *testing.T) {
252 // The value 100 is chosen so that sum of header fields bytes
253 // does not exceed it. We use > 100 bytes URI to exceed this
255 st := newServerTester([]string{"--header-field-buffer=100"}, t, func(w http.ResponseWriter, r *http.Request) {
256 t.Fatal("execution path should not be here")
260 res, err := st.http1(requestParam{
261 name: "TestH1H1HeaderFieldBufferPath",
262 path: "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
265 t.Fatalf("Error st.http1() = %v", err)
267 if got, want := res.status, 431; got != want {
268 t.Errorf("status: %v; want %v", got, want)
272 // TestH1H1HeaderFieldBuffer tests that request with header fields
273 // larger than configured buffer size is rejected.
274 func TestH1H1HeaderFieldBuffer(t *testing.T) {
275 st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
276 t.Fatal("execution path should not be here")
280 res, err := st.http1(requestParam{
281 name: "TestH1H1HeaderFieldBuffer",
284 t.Fatalf("Error st.http1() = %v", err)
286 if got, want := res.status, 431; got != want {
287 t.Errorf("status: %v; want %v", got, want)
291 // TestH1H1HeaderFields tests that request with header fields more
292 // than configured number is rejected.
293 func TestH1H1HeaderFields(t *testing.T) {
294 st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
295 t.Fatal("execution path should not be here")
299 res, err := st.http1(requestParam{
300 name: "TestH1H1HeaderFields",
301 header: []hpack.HeaderField{
302 // Add extra header field to ensure that
303 // header field limit exceeds
304 pair("Connection", "close"),
308 t.Fatalf("Error st.http1() = %v", err)
310 if got, want := res.status, 431; got != want {
311 t.Errorf("status: %v; want %v", got, want)
315 // TestH1H2ConnectFailure tests that server handles the situation that
316 // connection attempt to HTTP/2 backend failed.
317 func TestH1H2ConnectFailure(t *testing.T) {
318 st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
321 // simulate backend connect attempt failure
324 res, err := st.http1(requestParam{
325 name: "TestH1H2ConnectFailure",
328 t.Fatalf("Error st.http1() = %v", err)
331 if got := res.status; got != want {
332 t.Errorf("status: %v; want %v", got, want)
336 // TestH1H2NoHost tests that server rejects request without Host
337 // header field for HTTP/2 backend.
338 func TestH1H2NoHost(t *testing.T) {
339 st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
340 t.Errorf("server should not forward bad request")
344 // without Host header field, we expect 400 response
345 if _, err := io.WriteString(st.conn, "GET / HTTP/1.1\r\nTest-Case: TestH1H2NoHost\r\n\r\n"); err != nil {
346 t.Fatalf("Error io.WriteString() = %v", err)
349 resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
351 t.Fatalf("Error http.ReadResponse() = %v", err)
355 if got := resp.StatusCode; got != want {
356 t.Errorf("status: %v; want %v", got, want)
360 // TestH1H2HTTP10 tests that server can accept HTTP/1.0 request
361 // without Host header field
362 func TestH1H2HTTP10(t *testing.T) {
363 st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
364 w.Header().Add("request-host", r.Host)
368 if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H2HTTP10\r\n\r\n"); err != nil {
369 t.Fatalf("Error io.WriteString() = %v", err)
372 resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
374 t.Fatalf("Error http.ReadResponse() = %v", err)
377 if got, want := resp.StatusCode, 200; got != want {
378 t.Errorf("status: %v; want %v", got, want)
380 if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
381 t.Errorf("request-host: %v; want %v", got, want)
385 // TestH1H2HTTP10NoHostRewrite tests that server generates host header
386 // field using actual backend server even if --no-http-rewrite is
388 func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
389 st := newServerTester([]string{"--http2-bridge", "--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
390 w.Header().Add("request-host", r.Host)
394 if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H2HTTP10NoHostRewrite\r\n\r\n"); err != nil {
395 t.Fatalf("Error io.WriteString() = %v", err)
398 resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
400 t.Fatalf("Error http.ReadResponse() = %v", err)
403 if got, want := resp.StatusCode, 200; got != want {
404 t.Errorf("status: %v; want %v", got, want)
406 if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
407 t.Errorf("request-host: %v; want %v", got, want)
411 // TestH1H2CrumbleCookie tests that Cookies are crumbled and assembled
412 // when forwarding to HTTP/2 backend link. go-nghttp2 server
413 // concatenates crumbled Cookies automatically, so this test is not
414 // much effective now.
415 func TestH1H2CrumbleCookie(t *testing.T) {
416 st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
417 if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
418 t.Errorf("Cookie: %v; want %v", got, want)
423 res, err := st.http1(requestParam{
424 name: "TestH1H2CrumbleCookie",
425 header: []hpack.HeaderField{
426 pair("Cookie", "alpha; bravo; charlie"),
430 t.Fatalf("Error st.http1() = %v", err)
432 if got, want := res.status, 200; got != want {
433 t.Errorf("status: %v; want %v", got, want)
437 // TestH1H2GenerateVia tests that server generates Via header field to and
438 // from backend server.
439 func TestH1H2GenerateVia(t *testing.T) {
440 st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
441 if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
442 t.Errorf("Via: %v; want %v", got, want)
447 res, err := st.http1(requestParam{
448 name: "TestH1H2GenerateVia",
451 t.Fatalf("Error st.http1() = %v", err)
453 if got, want := res.header.Get("Via"), "2 nghttpx"; got != want {
454 t.Errorf("Via: %v; want %v", got, want)
458 // TestH1H2AppendVia tests that server adds value to existing Via
459 // header field to and from backend server.
460 func TestH1H2AppendVia(t *testing.T) {
461 st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
462 if got, want := r.Header.Get("Via"), "foo, 1.1 nghttpx"; got != want {
463 t.Errorf("Via: %v; want %v", got, want)
465 w.Header().Add("Via", "bar")
469 res, err := st.http1(requestParam{
470 name: "TestH1H2AppendVia",
471 header: []hpack.HeaderField{
476 t.Fatalf("Error st.http1() = %v", err)
478 if got, want := res.header.Get("Via"), "bar, 2 nghttpx"; got != want {
479 t.Errorf("Via: %v; want %v", got, want)
483 // TestH1H2NoVia tests that server does not add value to existing Via
484 // header field to and from backend server.
485 func TestH1H2NoVia(t *testing.T) {
486 st := newServerTester([]string{"--http2-bridge", "--no-via"}, t, func(w http.ResponseWriter, r *http.Request) {
487 if got, want := r.Header.Get("Via"), "foo"; got != want {
488 t.Errorf("Via: %v; want %v", got, want)
490 w.Header().Add("Via", "bar")
494 res, err := st.http1(requestParam{
495 name: "TestH1H2NoVia",
496 header: []hpack.HeaderField{
501 t.Fatalf("Error st.http1() = %v", err)
503 if got, want := res.header.Get("Via"), "bar"; got != want {
504 t.Errorf("Via: %v; want %v", got, want)