Pass-through proxy with timeouts, size limits and a request log (closes #13)
check / check (push) Successful in 2m9s

The repo's first code, with the layout the prompts policies ask for:
Makefile, script/ entrypoints, a Dockerfile whose lint and test phases
gate the build, the Gitea workflow, the canonical dotfiles and
REPO_POLICIES.md. smallwebwaf passes each request to the app through
httputil.ReverseProxy within the four timeouts and two size limits,
works out the client's address behind trusted proxies, and writes one
JSON line per request. The tests run against real local servers.
SPEC.md now says what Go's HTTP server does before smallwebwaf sees a
request; make fmt only rewraps EVALUATION.md.

Model: opus-5-5
This commit is contained in:
2026-10-03 14:19:01 +00:00
parent fd77e76177
commit 545ce67f44
45 changed files with 4869 additions and 74 deletions
+18 -8
View File
@@ -1,8 +1,8 @@
# smallwebwaf SPEC (draft): protective reverse proxy for one app
Status: fourth draft, with the owner's rulings to date applied. Nothing has been
built yet. `EVALUATION.md` beside this file explains why no existing tool was
chosen.
Status: fourth draft, with the owner's rulings to date applied. Milestone 1 of
the build order is built. `EVALUATION.md` beside this file explains why no
existing tool was chosen.
## Purpose
@@ -409,7 +409,8 @@ The settings, by group:
Bodies stream straight through, so a request body reaches the app while the
client is still sending it.
- `SWWAF_CLIENT_REQUEST_TIMEOUT` (default `60s`): how long a client may take
to send its whole request, headers and body.
to send its request line and headers, and then, from the end of the
headers, its body.
- `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` (default `32K`): the largest
request line and headers a client may send. Over it, `smallwebwaf` answers
`431` and closes the connection, and nothing reaches the app.
@@ -436,6 +437,13 @@ The settings, by group:
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.
- 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
`SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` are answered `431` by the server
itself, which reads up to 4 KiB past the limit before it refuses. Neither
request 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
@@ -1012,10 +1020,12 @@ and the running `smallwebwaf` takes the edit in.
## Request log
One JSON object per line on stdout for every request, including refused ones.
stdout is always on. When `SWWAF_LOG_REMOTE_URL` is set the same lines are also
sent to the remote endpoint, so a deployment can stop depending on docker's log
handling while `docker logs` keeps working.
One JSON object per line on stdout for every request, including refused ones,
apart from those Go's HTTP server ends before `smallwebwaf` sees them (see
"Configuration surface", size and time limits). stdout is always on. When
`SWWAF_LOG_REMOTE_URL` is set the same lines are also sent to the remote
endpoint, so a deployment can stop depending on docker's log handling while
`docker logs` keeps working.
- Standard web log fields: `time` (RFC 3339 with milliseconds), `instance`,
`client_ip`, `method`, `scheme`, `host`, `path`, `query`, `protocol`,