diff --git a/integration-tests/nghttpx_http1_test.go b/integration-tests/nghttpx_http1_test.go index cbddc13a..dd29f262 100644 --- a/integration-tests/nghttpx_http1_test.go +++ b/integration-tests/nghttpx_http1_test.go @@ -9,6 +9,7 @@ import ( "golang.org/x/net/websocket" "io" "net/http" + "regexp" "syscall" "testing" "time" @@ -125,6 +126,54 @@ Content-Length: 0 // } // } +// TestH1H1AffinityCookie tests that affinity cookie is sent back in +// cleartext http. +func TestH1H1AffinityCookie(t *testing.T) { + st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1AffinityCookie", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar` + validCookie := regexp.MustCompile(pattern) + if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) { + t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern) + } +} + +// TestH1H1AffinityCookieTLS tests that affinity cookie is sent back +// in https. +func TestH1H1AffinityCookieTLS(t *testing.T) { + st := newServerTesterTLS([]string{"--alpn-h1", "--affinity-cookie"}, t, noopHandler) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1AffinityCookieTLS", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure` + validCookie := regexp.MustCompile(pattern) + if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) { + t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern) + } +} + // TestH1H1GracefulShutdown tests graceful shutdown. func TestH1H1GracefulShutdown(t *testing.T) { st := newServerTester(nil, t, noopHandler) diff --git a/integration-tests/nghttpx_http2_test.go b/integration-tests/nghttpx_http2_test.go index 9ec1c264..93fc25d7 100644 --- a/integration-tests/nghttpx_http2_test.go +++ b/integration-tests/nghttpx_http2_test.go @@ -1705,6 +1705,55 @@ func TestH2H1Code204TE(t *testing.T) { } } +// TestH2H1AffinityCookie tests that affinity cookie is sent back in +// cleartext http. +func TestH2H1AffinityCookie(t *testing.T) { + st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1AffinityCookie", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar` + validCookie := regexp.MustCompile(pattern) + if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) { + t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern) + } +} + +// TestH2H1AffinityCookieTLS tests that affinity cookie is sent back +// in https. +func TestH2H1AffinityCookieTLS(t *testing.T) { + st := newServerTesterTLS([]string{"--affinity-cookie"}, t, noopHandler) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1AffinityCookieTLS", + scheme: "https", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure` + validCookie := regexp.MustCompile(pattern) + if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) { + t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern) + } +} + // TestH2H1GracefulShutdown tests graceful shutdown. func TestH2H1GracefulShutdown(t *testing.T) { st := newServerTester(nil, t, noopHandler) diff --git a/integration-tests/server_tester.go b/integration-tests/server_tester.go index dd4c341f..d145519d 100644 --- a/integration-tests/server_tester.go +++ b/integration-tests/server_tester.go @@ -101,7 +101,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl args := []string{} - var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS bool + var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool for _, k := range src_args { switch k { @@ -116,6 +116,10 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl acceptProxyProtocol = true case "--redirect-if-not-tls": redirectIfNotTLS = true + case "--affinity-cookie": + affinityCookie = true + case "--alpn-h1": + alpnH1 = true default: args = append(args, k) } @@ -168,6 +172,10 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl b += ";redirect-if-not-tls" } + if affinityCookie { + b += ";affinity=cookie;affinity-cookie-name=affinity;affinity-cookie-path=/foo/bar" + } + noTLS := ";no-tls" if frontendTLS { noTLS = "" @@ -218,7 +226,11 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl tlsConfig = clientConfig } tlsConfig.InsecureSkipVerify = true - tlsConfig.NextProtos = []string{"h2", "spdy/3.1"} + if alpnH1 { + tlsConfig.NextProtos = []string{"http/1.1"} + } else { + tlsConfig.NextProtos = []string{"h2", "spdy/3.1"} + } conn, err = tls.Dial("tcp", authority, tlsConfig) } else { conn, err = net.Dial("tcp", authority)