From 026521b0971d1a70ac4490c565660446b9b44780 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 29 Apr 2015 22:54:25 +0900 Subject: [PATCH] integration: Add tests for --header-field-buffer and --max-header-fields --- integration-tests/nghttpx_http1_test.go | 66 +++++++++++++++++++++++++ integration-tests/nghttpx_http2_test.go | 40 +++++++++++++++ integration-tests/nghttpx_spdy_test.go | 40 +++++++++++++++ integration-tests/server_tester.go | 14 +++++- 4 files changed, 159 insertions(+), 1 deletion(-) diff --git a/integration-tests/nghttpx_http1_test.go b/integration-tests/nghttpx_http1_test.go index 80d3b1ca..c8d58709 100644 --- a/integration-tests/nghttpx_http1_test.go +++ b/integration-tests/nghttpx_http1_test.go @@ -246,6 +246,72 @@ func TestH1H1RequestTrailer(t *testing.T) { } } +// TestH1H1HeaderFieldBufferPath tests that request with request path +// larger than configured buffer size is rejected. +func TestH1H1HeaderFieldBufferPath(t *testing.T) { + // The value 100 is chosen so that sum of header fields bytes + // does not exceed it. We use > 100 bytes URI to exceed this + // limit. + st := newServerTester([]string{"--header-field-buffer=100"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1HeaderFieldBufferPath", + path: "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + if got, want := res.status, 431; got != want { + t.Errorf("status: %v; want %v", got, want) + } +} + +// TestH1H1HeaderFieldBuffer tests that request with header fields +// larger than configured buffer size is rejected. +func TestH1H1HeaderFieldBuffer(t *testing.T) { + st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1HeaderFieldBuffer", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + if got, want := res.status, 431; got != want { + t.Errorf("status: %v; want %v", got, want) + } +} + +// TestH1H1HeaderFields tests that request with header fields more +// than configured number is rejected. +func TestH1H1HeaderFields(t *testing.T) { + st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1HeaderFields", + header: []hpack.HeaderField{ + // Add extra header field to ensure that + // header field limit exceeds + pair("Connection", "close"), + }, + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + if got, want := res.status, 431; got != want { + t.Errorf("status: %v; want %v", got, want) + } +} + // TestH1H2ConnectFailure tests that server handles the situation that // connection attempt to HTTP/2 backend failed. func TestH1H2ConnectFailure(t *testing.T) { diff --git a/integration-tests/nghttpx_http2_test.go b/integration-tests/nghttpx_http2_test.go index 89cd353a..0a3115f3 100644 --- a/integration-tests/nghttpx_http2_test.go +++ b/integration-tests/nghttpx_http2_test.go @@ -558,6 +558,46 @@ func TestH2H1RequestTrailer(t *testing.T) { } } +// TestH2H1HeaderFieldBuffer tests that request with header fields +// larger than configured buffer size is rejected. +func TestH2H1HeaderFieldBuffer(t *testing.T) { + st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1HeaderFieldBuffer", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + if got, want := res.status, 431; got != want { + t.Errorf("status: %v; want %v", got, want) + } +} + +// TestH2H1HeaderFields tests that request with header fields more +// than configured number is rejected. +func TestH2H1HeaderFields(t *testing.T) { + st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1HeaderFields", + // we have at least 4 pseudo-header fields sent, and + // that ensures that buffer limit exceeds. + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + if got, want := res.status, 431; got != want { + t.Errorf("status: %v; want %v", got, want) + } +} + // TestH2H1Upgrade tests HTTP Upgrade to HTTP/2 func TestH2H1Upgrade(t *testing.T) { st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {}) diff --git a/integration-tests/nghttpx_spdy_test.go b/integration-tests/nghttpx_spdy_test.go index 0b289397..232e1da8 100644 --- a/integration-tests/nghttpx_spdy_test.go +++ b/integration-tests/nghttpx_spdy_test.go @@ -170,6 +170,46 @@ func TestS3H1NoVia(t *testing.T) { } } +// TestS3H1HeaderFieldBuffer tests that request with header fields +// larger than configured buffer size is rejected. +func TestS3H1HeaderFieldBuffer(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H1HeaderFieldBuffer", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + if got, want := res.spdyRstErrCode, spdy.InternalError; got != want { + t.Errorf("res.spdyRstErrCode: %v; want %v", got, want) + } +} + +// TestS3H1HeaderFields tests that request with header fields more +// than configured number is rejected. +func TestS3H1HeaderFields(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatal("execution path should not be here") + }) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H1HeaderFields", + // we have at least 5 pseudo-header fields sent, and + // that ensures that buffer limit exceeds. + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + if got, want := res.spdyRstErrCode, spdy.InternalError; got != want { + t.Errorf("res.spdyRstErrCode: %v; want %v", got, want) + } +} + // TestS3H2ConnectFailure tests that server handles the situation that // connection attempt to HTTP/2 backend failed. func TestS3H2ConnectFailure(t *testing.T) { diff --git a/integration-tests/server_tester.go b/integration-tests/server_tester.go index 3a4b5568..87e593b8 100644 --- a/integration-tests/server_tester.go +++ b/integration-tests/server_tester.go @@ -297,7 +297,19 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) { body = cbr } } - req, err := http.NewRequest(method, st.url, body) + + reqURL := st.url + + if rp.path != "" { + u, err := url.Parse(st.url) + if err != nil { + st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err) + } + u.Path = rp.path + reqURL = u.String() + } + + req, err := http.NewRequest(method, reqURL, body) if err != nil { return nil, err }