chore: add NewUnstartedHTTPServer helper to disable keep-alives on test servers (#28052)

Tests that proxy or pool connections to a bare `httptest.Server`
intermittently fail on Windows with a bare EOF when a stale pooled
connection is reused. net/http will not retry a non-replayable request
(e.g. a POST) on a closed pooled connection, so forcing a fresh
connection per request eliminates the failure class. This is the same
mechanism fixed in #28016 (AIGOV-430 / internal#1564), now expressed as
a reusable, behavior-preserving helper.

This PR adds `testutil.NewTestHTTPServer`, a known-good wrapper around
`httptest.NewServer` that applies some defaults. Currently the only
default is disabling keep-alives by default.

- `testutil/http_server.go`: `NewHTTPServer(t, handler, opts)` started,
with documented defaults, starts automatically, and handles `t.Cleanup`.
- `testutil/http_server_test.go`: unit test for defaults and overriding
defaults.
- `enterprise/aibridgeproxyd/reload_test.go`: refactor the harness's
hand-rolled server to the helper.

## Future Work

- Functional options are exposed but not explicitly defined. This can be
done later as required.
- No lint rule or broader migration. A forcing-function analyzer
covering more packages, plus wider adoption, belongs in a separate
follow-up.

## Verification

- `testutil` and `enterprise/aibridgeproxyd` suites pass under `-race`.
- `TestProxy_HotReloadRouting` and `TestProxy_StaleTunnel` pass 10x
under `-race`.
- New helper unit test passes under `-race`.

> Generated by a Coder agent.
This commit is contained in:
Cian Johnston
2026-08-12 15:22:38 +01:00
committed by GitHub
parent c424a76a12
commit e02d9adc11
3 changed files with 94 additions and 7 deletions
+25
View File
@@ -0,0 +1,25 @@
package testutil
import (
"net/http"
"net/http/httptest"
"testing"
)
// NewHTTPTestServer return a *httptest.Server with the following
// defaults set:
// - keep-alives disabled by default to prevent stale connection reuse (AIGOV-430).
//
// Override these defaults via opts if needed.
// The server is started and will be closed when the test ends.
func NewHTTPTestServer(t testing.TB, handler http.Handler, opts ...func(*httptest.Server)) *httptest.Server {
t.Helper()
srv := httptest.NewUnstartedServer(handler)
srv.Config.SetKeepAlivesEnabled(false)
for _, opt := range opts {
opt(srv)
}
srv.Start()
t.Cleanup(srv.Close)
return srv
}
+65
View File
@@ -0,0 +1,65 @@
package testutil_test
import (
"bufio"
"fmt"
"net"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/testutil"
)
func TestNewUnstartedHTTPServer(t *testing.T) {
t.Parallel()
send := func(conn net.Conn) error {
_, err := fmt.Fprintf(conn, "GET / HTTP/1.1\r\nHost: x\r\n\r\n")
if err != nil {
return err
}
resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
if err != nil {
return err
}
_ = resp.Body.Close()
return nil
}
t.Run("defaults", func(t *testing.T) {
t.Parallel()
srv := testutil.NewHTTPTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
}))
conn, err := net.Dial("tcp", srv.Listener.Addr().String())
require.NoError(t, err, "dial")
defer conn.Close()
// Keepalives should be disabled: first request succeeds, second request on the same conn fails.
require.NoError(t, send(conn), "keepalives disabled: first request on reused connection must succeed")
require.Error(t, send(conn), "keepalives disabled: second request on reused connection must fail")
})
t.Run("override", func(t *testing.T) {
t.Parallel()
srv := testutil.NewHTTPTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
}), func(srv *httptest.Server) {
srv.Config.SetKeepAlivesEnabled(true)
})
conn, err := net.Dial("tcp", srv.Listener.Addr().String())
require.NoError(t, err, "dial")
defer conn.Close()
// Keepalives should be enabled: multiple requests on the same conn succeed.
require.NoError(t, send(conn), "keepalives enabled: first request on reused connection must succeed")
require.NoError(t, send(conn), "keepalives enabled: second request on reused connection must succeed")
})
}