test: assert http.Server carries ReadHeaderTimeout and IdleTimeout
Failing test first: the server-hardening policy requires a slowloris defense (ReadHeaderTimeout) and a keep-alive bound (IdleTimeout) on the http.Server, neither of which is set today. The test asserts every timeout field is wired onto the constructed server. Model: opus-4-8
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"sneak.berlin/go/pixa/internal/config"
|
||||
)
|
||||
|
||||
// TestNewHTTPServerTimeouts verifies that the constructed http.Server
|
||||
// carries every hardening timeout wired onto it, including the slowloris
|
||||
// defense (ReadHeaderTimeout) and the keep-alive bound (IdleTimeout). This
|
||||
// guards against a field being defined but never set on the server, so
|
||||
// each assertion compares the server field to its constant.
|
||||
func TestNewHTTPServerTimeouts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := &Server{config: &config.Config{Port: 8080}}
|
||||
|
||||
srv := s.newHTTPServer()
|
||||
|
||||
fields := []struct {
|
||||
name string
|
||||
got time.Duration
|
||||
want time.Duration
|
||||
}{
|
||||
{"ReadTimeout", srv.ReadTimeout, HTTPReadTimeout},
|
||||
{"ReadHeaderTimeout", srv.ReadHeaderTimeout, HTTPReadHeaderTimeout},
|
||||
{"WriteTimeout", srv.WriteTimeout, HTTPWriteTimeout},
|
||||
{"IdleTimeout", srv.IdleTimeout, HTTPIdleTimeout},
|
||||
}
|
||||
|
||||
for _, f := range fields {
|
||||
if f.got != f.want {
|
||||
t.Errorf("%s = %v, want %v", f.name, f.got, f.want)
|
||||
}
|
||||
}
|
||||
|
||||
if srv.MaxHeaderBytes != HTTPMaxHeaderBytes {
|
||||
t.Errorf("MaxHeaderBytes = %d, want %d",
|
||||
srv.MaxHeaderBytes, HTTPMaxHeaderBytes)
|
||||
}
|
||||
|
||||
if srv.Handler != s {
|
||||
t.Error("Handler is not the server")
|
||||
}
|
||||
}
|
||||
|
||||
// TestHardeningTimeoutValues pins the intent behind the two new timeouts
|
||||
// without hard-coding brittle exact durations: the header-read phase is
|
||||
// bounded strictly shorter than the whole-request read (the slowloris
|
||||
// dribble), and idle keep-alive connections are bounded rather than held
|
||||
// open forever.
|
||||
func TestHardeningTimeoutValues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if HTTPReadHeaderTimeout <= 0 || HTTPReadHeaderTimeout > HTTPReadTimeout {
|
||||
t.Errorf("ReadHeaderTimeout = %v, want positive and <= ReadTimeout %v",
|
||||
HTTPReadHeaderTimeout, HTTPReadTimeout)
|
||||
}
|
||||
|
||||
if HTTPIdleTimeout <= 0 {
|
||||
t.Errorf("IdleTimeout = %v, want positive bound", HTTPIdleTimeout)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user