From 39410c859401a40aeccf768e49f51e7a8ea4a160 Mon Sep 17 00:00:00 2001 From: Andriy Palamarchuk Date: Sat, 3 Oct 2026 15:37:22 -0400 Subject: [PATCH] test(proxy): serve proxy test upstreams locally Five proxy tests forwarded allowed requests to dev.coder.com and jsonplaceholder.typicode.com over the internet. dev.coder.com now answers with a 301 to dogfood.cdr.dev, so TestProxyServerImplicitCONNECT and TestMultipleRequestsOverExplicitCONNECT fail on main, and the tests also fail wherever there is no internet. Add a WithFakeUpstream option that points the proxy's forward transport at local httptest servers (TLS for port 443, plain HTTP otherwise), plus a handler with the canned responses those hosts used to return. The tests keep their hostnames, so they still check that each request in a tunnel is forwarded to the host in its Host header. Co-Authored-By: Claude Opus 5.5 (1M context) --- proxy/proxy_audit_test.go | 1 + proxy/proxy_connect_test.go | 26 ++++------------ proxy/proxy_framework_test.go | 56 +++++++++++++++++++++++++++++++++++ proxy/proxy_test.go | 14 +++------ 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/proxy/proxy_audit_test.go b/proxy/proxy_audit_test.go index 0e591e22..477eed50 100644 --- a/proxy/proxy_audit_test.go +++ b/proxy/proxy_audit_test.go @@ -166,6 +166,7 @@ func TestAuditURLIsFullyFormed_HTTPS(t *testing.T) { WithCertManager(t.TempDir()), WithAllowedDomain("dev.coder.com"), WithAuditor(auditor), + WithFakeUpstream(fakePublicHosts()), ).Start() defer pt.Stop() diff --git a/proxy/proxy_connect_test.go b/proxy/proxy_connect_test.go index 17b1227c..ea80b359 100644 --- a/proxy/proxy_connect_test.go +++ b/proxy/proxy_connect_test.go @@ -13,29 +13,22 @@ func TestProxyServerImplicitCONNECT(t *testing.T) { WithCertManager("/tmp/boundary_connect_test"), WithAllowedDomain("dev.coder.com"), WithAllowedDomain("jsonplaceholder.typicode.com"), + WithFakeUpstream(fakePublicHosts()), ). Start() defer pt.Stop() // Test HTTPS request through proxy transport (automatic CONNECT) t.Run("HTTPSRequestThroughProxyTransport", func(t *testing.T) { - expectedResponse := `{"message":"👋"} -` // Because this is HTTPS, Go will issue CONNECT localhost:8080 → dev.coder.com:443 - pt.ExpectAllowedViaProxy("https://dev.coder.com/api/v2", expectedResponse) + pt.ExpectAllowedViaProxy("https://dev.coder.com/api/v2", devCoderAPIResponse) }) // Test HTTP request through proxy transport t.Run("HTTPRequestThroughProxyTransport", func(t *testing.T) { - expectedResponse := `{ - "userId": 1, - "id": 1, - "title": "delectus aut autem", - "completed": false -}` // For HTTP requests, Go will send the request directly to the proxy // The proxy will forward it to the target server - pt.ExpectAllowedViaProxy("http://jsonplaceholder.typicode.com/todos/1", expectedResponse) + pt.ExpectAllowedViaProxy("http://jsonplaceholder.typicode.com/todos/1", todoResponse) }) } @@ -45,6 +38,7 @@ func TestMultipleRequestsOverExplicitCONNECT(t *testing.T) { WithCertManager("/tmp/boundary_explicit_connect_test"), WithAllowedDomain("dev.coder.com"), WithAllowedDomain("jsonplaceholder.typicode.com"), + WithFakeUpstream(fakePublicHosts()), ). Start() defer pt.Stop() @@ -60,22 +54,14 @@ func TestMultipleRequestsOverExplicitCONNECT(t *testing.T) { t.Run("AllowedRequestToDevCoder", func(t *testing.T) { body1, err := tunnel.sendRequest("dev.coder.com", "/api/v2") require.NoError(t, err, "Failed to send first request") - expectedResponse1 := `{"message":"👋"} -` - require.Equal(t, expectedResponse1, string(body1), "First response does not match") + require.Equal(t, devCoderAPIResponse, string(body1), "First response does not match") }) // Positive test: Send second request to a different domain (jsonplaceholder.typicode.com) over the same tunnel t.Run("AllowedRequestToJsonPlaceholder", func(t *testing.T) { body2, err := tunnel.sendRequest("jsonplaceholder.typicode.com", "/todos/1") require.NoError(t, err, "Failed to send second request") - expectedResponse2 := `{ - "userId": 1, - "id": 1, - "title": "delectus aut autem", - "completed": false -}` - require.Equal(t, expectedResponse2, string(body2), "Second response does not match") + require.Equal(t, todoResponse, string(body2), "Second response does not match") }) // Negative test: Try to send request to a blocked domain over the same tunnel diff --git a/proxy/proxy_framework_test.go b/proxy/proxy_framework_test.go index 9ccad67e..8d5b0eba 100644 --- a/proxy/proxy_framework_test.go +++ b/proxy/proxy_framework_test.go @@ -2,6 +2,7 @@ package proxy import ( "bufio" + "context" "crypto/tls" "fmt" "io" @@ -137,6 +138,61 @@ func WithForwardTransport(transport http.RoundTripper) ProxyTestOption { } } +// Canned upstream responses. +const ( + devCoderAPIResponse = "{\"message\":\"👋\"}\n" + todoResponse = `{ + "userId": 1, + "id": 1, + "title": "delectus aut autem", + "completed": false +}` +) + +// fakePublicHosts serves canned responses for the public hosts that proxy +// tests allow, so the tests do not depend on those hosts being reachable or +// unchanged. Use it with WithFakeUpstream. +func fakePublicHosts() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Host == "dev.coder.com" && r.URL.Path == "/api/v2": + _, _ = io.WriteString(w, devCoderAPIResponse) + case r.Host == "jsonplaceholder.typicode.com" && r.URL.Path == "/todos/1": + _, _ = io.WriteString(w, todoResponse) + default: + http.NotFound(w, r) + } + }) +} + +// WithFakeUpstream makes the proxy forward allowed requests to local test +// servers running handler instead of the internet. Requests for port 443 +// reach a TLS server, and all others reach a plain HTTP server. The handler +// sees the original Host header. +func WithFakeUpstream(handler http.Handler) ProxyTestOption { + return func(pt *ProxyTest) { + plain := httptest.NewServer(handler) + secure := httptest.NewTLSServer(handler) + pt.t.Cleanup(plain.Close) + pt.t.Cleanup(secure.Close) + + transport := secure.Client().Transport.(*http.Transport).Clone() + // The httptest certificate is valid for example.com rather than for + // the hosts that tests request. + transport.TLSClientConfig.ServerName = "example.com" + transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { + target := plain.Listener.Addr().String() + if _, port, err := net.SplitHostPort(addr); err == nil && port == "443" { + target = secure.Listener.Addr().String() + } + var dialer net.Dialer + return dialer.DialContext(ctx, network, target) + } + pt.t.Cleanup(transport.CloseIdleConnections) + pt.forwardTransport = transport + } +} + // Start starts the proxy server func (pt *ProxyTest) Start() *ProxyTest { pt.t.Helper() diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index ffd1c8d5..ec600144 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -8,18 +8,13 @@ import ( func TestProxyServerBasicHTTP(t *testing.T) { pt := NewProxyTest(t, WithAllowedDomain("jsonplaceholder.typicode.com"), + WithFakeUpstream(fakePublicHosts()), ). Start() defer pt.Stop() t.Run("BasicHTTPRequest", func(t *testing.T) { - expectedResponse := `{ - "userId": 1, - "id": 1, - "title": "delectus aut autem", - "completed": false -}` - pt.ExpectAllowed("http://localhost:8080/todos/1", "jsonplaceholder.typicode.com", expectedResponse) + pt.ExpectAllowed("http://localhost:8080/todos/1", "jsonplaceholder.typicode.com", todoResponse) }) t.Run("BlockedHTTPRequest", func(t *testing.T) { @@ -49,14 +44,13 @@ func TestProxyServerBasicHTTPS(t *testing.T) { pt := NewProxyTest(t, WithCertManager("/tmp/boundary"), WithAllowedDomain("dev.coder.com"), + WithFakeUpstream(fakePublicHosts()), ). Start() defer pt.Stop() t.Run("BasicHTTPSRequest", func(t *testing.T) { - expectedResponse := `{"message":"👋"} -` - pt.ExpectAllowed("https://localhost:8080/api/v2", "dev.coder.com", expectedResponse) + pt.ExpectAllowed("https://localhost:8080/api/v2", "dev.coder.com", devCoderAPIResponse) }) t.Run("BlockedHTTPSRequest", func(t *testing.T) {