The header size and the idle time as settings (closes #70)
check / check (push) Successful in 3m26s
check / check (push) Successful in 3m26s
SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES (default 32K) and SWWAF_CLIENT_IDLE_TIMEOUT (default 120s) replace the two values the proxy fixed. The idle time is read like the other durations, and can be off. Go's server reads 4K past the header limit it is given before it refuses, so it is still given the setting less 4K. The header size must be more than 4K and cannot be off; any other value stops the start with a message that does not offer off. SPEC.md and README.md say so. README.md lists both settings, no longer calls them fixed, and names them as built. Model: opus-5-5
This commit is contained in:
@@ -297,7 +297,7 @@ func echoAfterUpgrade(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerHasTheFixedLimits(t *testing.T) {
|
||||
func TestServerHasTheDefaultLimits(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg, err := config.FromEnvironment(func(string) (string, bool) { return "", false })
|
||||
@@ -319,37 +319,48 @@ func TestServerHasTheFixedLimits(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefusesHeadersOver32KiB(t *testing.T) {
|
||||
func TestRefusesHeadersOverTheLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var calls atomic.Int32
|
||||
|
||||
app := startApp(t, func(http.ResponseWriter, *http.Request) {
|
||||
calls.Add(1)
|
||||
})
|
||||
addr, _ := startProxy(t, app.URL, nil)
|
||||
|
||||
// size counts every byte of the request: the request line, the
|
||||
// headers and the blank line that ends them.
|
||||
const (
|
||||
start = "GET / HTTP/1.1\r\nHost: app\r\nX-Large: "
|
||||
end = "\r\n\r\n"
|
||||
)
|
||||
|
||||
for _, tc := range []struct {
|
||||
size int
|
||||
want int
|
||||
name string
|
||||
env map[string]string
|
||||
limit int
|
||||
}{
|
||||
{size: 32 << 10, want: http.StatusOK},
|
||||
{size: 32<<10 + 1, want: http.StatusRequestHeaderFieldsTooLarge},
|
||||
{"by default", nil, 32 << 10},
|
||||
{"as set", map[string]string{clientHeaderMaxBytes: "8K"}, 8 << 10},
|
||||
} {
|
||||
conn := dial(t, addr)
|
||||
send(t, conn, start+strings.Repeat("a", tc.size-len(start)-len(end))+end)
|
||||
wantStatus(t, readResponse(t, conn), tc.want)
|
||||
}
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if calls.Load() != 1 {
|
||||
t.Errorf("the app was called %d times, want once", calls.Load())
|
||||
var calls atomic.Int32
|
||||
|
||||
app := startApp(t, func(http.ResponseWriter, *http.Request) {
|
||||
calls.Add(1)
|
||||
})
|
||||
addr, _ := startProxy(t, app.URL, tc.env)
|
||||
|
||||
// size counts every byte of the request: the request line,
|
||||
// the headers and the blank line that ends them.
|
||||
const (
|
||||
start = "GET / HTTP/1.1\r\nHost: app\r\nX-Large: "
|
||||
end = "\r\n\r\n"
|
||||
)
|
||||
|
||||
for _, sent := range []struct{ size, want int }{
|
||||
{tc.limit, http.StatusOK},
|
||||
{tc.limit + 1, http.StatusRequestHeaderFieldsTooLarge},
|
||||
} {
|
||||
conn := dial(t, addr)
|
||||
send(t, conn,
|
||||
start+strings.Repeat("a", sent.size-len(start)-len(end))+end)
|
||||
wantStatus(t, readResponse(t, conn), sent.want)
|
||||
}
|
||||
|
||||
if calls.Load() != 1 {
|
||||
t.Errorf("the app was called %d times, want once", calls.Load())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user