Rate limit: a hundred at once, ten a second, and the page's own files are not counted
Test / test (pull_request) Successful in 1m15s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
This commit is contained in:
Bendik Aagaard Lynghaug
2026-09-30 19:51:48 +02:00
co-authored by Claude Opus 5.5
parent 3604683df3
commit 87d4dda0eb
3 changed files with 74 additions and 51 deletions
+16 -7
View File
@@ -82,22 +82,31 @@ values.
| `GARAGE_*` | uploads |
| `MAPBOX_TOKEN` | map tiles, proxied; unset, maps are off |
| `GARAGE_*` (4) | attachments; see below. Unset, upload fields fail closed |
| `PORTAL_RATE_BURST`, `PORTAL_RATE_SECONDS` | the rate limit; see below |
| `PORTAL_RATE_BURST`, `PORTAL_RATE_PER_SECOND` | the rate limit; see below |
Mail is delivered by [gdo](https://project.uhhm.no/uhhm/gdo), a
separate unit on the same host reading the same NATS.
## Rate limiting
Every request passes a per-caller-IP limit before a session is loaded
or a handler is entered: a burst of 30, refilled one every two
seconds. A visitor filling in a form never reaches it (a page load
fetches several resources at once); a script does.
Every request that makes portal do something passes a per-caller-IP
limit before a session is loaded or a handler is entered: a burst of
100, refilled at ten a second. More than a hundred requests in ten
seconds is a script; someone reloading a page again and again stays
well inside it.
The files a page is made of, served from portal's own disk, are not
counted: the stylesheet and scripts under `/pkg`, the fonts, the
favicons, the vendored libraries. Refusing one of those is what turns
a reloaded page into an unstyled mess, and serving one costs next to
nothing. Anything that makes portal ask someone else is counted: a
content picture under `/site/` is fetched from Gitea, a map tile from
the map provider.
| | |
|---|---|
| `PORTAL_RATE_BURST` | how many requests at once, default 30 |
| `PORTAL_RATE_SECONDS` | seconds per refilled request, default 2 |
| `PORTAL_RATE_BURST` | how many requests at once, default 100 |
| `PORTAL_RATE_PER_SECOND` | requests refilled per second, default 10 |
Either set to `0` turns it off, for an instance behind something that
already does this. The caller is read from `X-Forwarded-For` or