From baa90d7625875d5ee552c5dba1ffc80de47e45f2 Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 20 Oct 2026 11:08:30 +0000 Subject: [PATCH] README and SPEC say when a client too slow to send its request line or headers is answered 400 (closes #138) When SWWAF_CLIENT_REQUEST_TIMEOUT runs out partway through a line, Go's server reads the part that arrived, a carriage return without its line feed included, as the whole line. If that part cannot be read as a line, it answers 400; otherwise it closes the connection without an answer. The README's "Request log" and SPEC's size and time limits said such a client always gets no answer, and both documents' summaries of answers gave 408 for any slow client, when it is only for a slow body. Model: opus-5-5 --- README.md | 21 +++++++++++++-------- SPEC.md | 21 +++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 3d706dc..5bbf2e6 100644 --- a/README.md +++ b/README.md @@ -112,11 +112,11 @@ in `bin/state` unless `SWWAF_STATE_DIR` is set, and the default rule file of log line (see `request_id` in "Request log" below). - Enforces the timeouts and the size limits below. A limit passed before the response has started gets `smallwebwaf`'s own answer: `408` for a client too - slow to send its request, `413` for a request body that is too large, `504` - for an app too slow to answer, and `502` for a response that is too large or - an app that cannot be reached. A request that announces a body over the limit - is refused before anything reaches the app. While a request body is still on - its way, a request timeout that runs out answers `408` if `smallwebwaf` was + slow to send its body, `413` for a request body that is too large, `504` for + an app too slow to answer, and `502` for a response that is too large or an + app that cannot be reached. A request that announces a body over the limit is + refused before anything reaches the app. While a request body is still on its + way, a request timeout that runs out answers `408` if `smallwebwaf` was waiting for the client to send more, and `504` if it was waiting for the app to take what it had. Once the response has started, a limit can only cut the connection. @@ -1042,9 +1042,14 @@ less severe than `SWWAF_LOG_LEVEL` are not written. Go's HTTP server, on which `smallwebwaf` is built, reads a request's line and headers before `smallwebwaf` sees the request, and some requests end there, without a line in the log: headers over `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES`, -which it answers `431`, headers slower than `SWWAF_CLIENT_REQUEST_TIMEOUT`, -whose connection it closes without an answer, and requests it cannot read at -all, which it answers itself, mostly with `400`. +which it answers `431`, requests it cannot read at all, which it answers itself, +mostly with `400`, and a request line and headers slower than +`SWWAF_CLIENT_REQUEST_TIMEOUT`. When that time runs out, the server takes what +has arrived of the line it is reading for the whole line, and answers `400` if +that is not a line it can read, as for a request line cut before the end of its +HTTP version, a header cut before its colon, or a line cut between its carriage +return and line feed. Otherwise, as for a client that stops right after a line +feed, it closes the connection without an answer. ### Sending the log to a syslog server diff --git a/SPEC.md b/SPEC.md index c6e8fb3..2c3c5d4 100644 --- a/SPEC.md +++ b/SPEC.md @@ -437,10 +437,10 @@ The settings, by group: the app sends it and the client receives it. - When a limit is passed before the response has started, `smallwebwaf` answers itself: `413` for a request body that is too large, `408` for a - client that is too slow, `502` for a response that is too large, `504` for - an app that is too slow. A request that announces a body larger than its - limit is refused before anything reaches the app. Once the response has - started it can only be cut off, and the connection is closed. + client too slow to send its body, `502` for a response that is too large, + `504` for an app that is too slow. A request that announces a body larger + than its limit is refused before anything reaches the app. Once the + response has started it can only be cut off, and the connection is closed. - Since a request body streams through, each side can hold up the other: a slow client slows the send to the app, and an app slow to take the body slows the client's send. So while a request body is still on its way, a @@ -449,11 +449,16 @@ The settings, by group: waiting for the client to send more at that moment, and `504` if it was waiting for the app to take what it had. - Go's HTTP server, on which `smallwebwaf` is built, reads a request's line - and headers before `smallwebwaf` sees the request. A client that takes - longer than `SWWAF_CLIENT_REQUEST_TIMEOUT` to send them gets no answer: - the server closes its connection. Headers over + and headers before `smallwebwaf` sees the request. When + `SWWAF_CLIENT_REQUEST_TIMEOUT` runs out before they have all arrived, the + server takes what has arrived of the line it is reading for the whole + line, and answers `400` if that is not a line it can read, as for a + request line cut before the end of its HTTP version, a header cut before + its colon, or a line cut between its carriage return and line feed. + Otherwise, as for a client that stops right after a line feed, it closes + the connection without an answer. Headers over `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` are answered `431` by the server - itself. Neither request gets a line in the request log. + itself. None of these requests gets a line in the request log. - A WebSocket connection leaves these limits behind once it is upgraded: it stays open until either side closes it. - Lookup of AS number and country (R7). On by default through GeoJS, which needs