internal/server/boot/httpserver_test.go
Ref: Size: 2.1 KiB History
package boot
import (
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
// TestHTTPServerBoundsSlowClientsWithoutCappingStreams pins the timeout posture
// of the plane's HTTP server: the header phase and idle keep-alives are bounded
// (Slowloris defense, fd reclamation), while ReadTimeout and WriteTimeout stay
// off so the SSE event stream and the serial-console WebSocket — both long-lived
// by design — are never cut at a deadline.
//
// The two bounded values are asserted against literals, not against the
// constants that set them: a deadline compared to itself passes at zero.
func TestHTTPServerBoundsSlowClientsWithoutCappingStreams(t *testing.T) {
srv := httpServer(":0", http.NewServeMux())
assert.GreaterOrEqual(t, srv.ReadHeaderTimeout, time.Second,
"ReadHeaderTimeout must bound how long a client may dribble request headers: at 0 there is no deadline at all, "+
"a single host holds a goroutine and an fd open forever, and a few hundred of them exhaust the listener. "+
"This is the Slowloris guard and it is the only one — ReadTimeout is deliberately left 0 so SSE and console "+
"WebSocket streams survive, so nothing else bounds the header phase")
assert.LessOrEqual(t, srv.ReadHeaderTimeout, 30*time.Second,
"a header phase measured in minutes is as good as unbounded: the attack is cheap precisely because an unfinished "+
"request costs the client nothing to hold")
assert.GreaterOrEqual(t, srv.IdleTimeout, 10*time.Second,
"IdleTimeout must reclaim a keep-alive connection that has gone quiet between requests: at 0 net/http never closes "+
"an idle connection, so every probe that opens one and walks away costs an fd until the process restarts. "+
"It applies only while idle, never mid-request, so a live stream is untouched")
assert.LessOrEqual(t, srv.IdleTimeout, 10*time.Minute,
"an idle window measured in hours reclaims nothing on the timescale a flood works at")
assert.Zero(t, srv.ReadTimeout, "a whole-request read deadline would cancel the SSE stream")
assert.Zero(t, srv.WriteTimeout, "a whole-request write deadline would sever a live console")
}