#405 · Per-address limits use each client's connecting address behind Next.js
- timeline-app
- pull request
## Summary Next.js route handlers receive a web `Request` with no connection, so `dispatchNextRequest` set every request's address to `'unknown'`. Unless `TRUST_PROXY=1` was set, all per-address limits (sign-in, registration, device and OAuth starts, two-factor, password reset, reports, challenges and SQLite downloads) counted every client together. - `server/peer-address.cjs` is put at the top of the standalone launcher (`server.cjs`) by `scripts/build-platform.mjs`. It writes each request's `socket.remoteAddress` into the `X-OC-Peer-Address` request header before Next.js reads it, which replaces any value a client sent. The value starts with a random secret created when the server starts. - `next-handler.mjs` uses the header only when it carries that secret, and removes it before calling the handler. Without the launcher (`next dev`), the address stays `'unknown'` as before. - `X-Forwarded-For` is still used only with `TRUST_PROXY=1`, unchanged. - `http.mjs` logs one warning when requests from loopback carry a different `X-Forwarded-For` while `TRUST_PROXY` is not 1. That is a proxy on the same machine, and every client would be counted as the proxy. - The docs (README, docker.md, authentication.md) now say that without `TRUST_PROXY=1` the address is the proxy's, or Docker's gateway under Compose. Every entry point (`npm start`, Docker, the Debian/RPM, FreeBSD, Homebrew and Windows launchers, and the tests) runs `server.cjs` built by `npm run build`, so all of them get the change. ## Tests - New `test/next-client-address-postgres.mjs`, also added to CI: runs the built platform with `TRUST_PROXY=0` and sends failed sign-ins from 127.0.0.2 until it gets 429. Forged `X-Forwarded-For` and `X-OC-Peer-Address` headers still get 429, 127.0.0.3 gets its own limit, and the local-proxy warning is logged. It fails without the launcher change (127.0.0.3 gets 429). - `test/next-route.test.mjs`: the bridge believes the header only with the secret, and removes it. - `npm test`, `node test/next-postgres.mjs` and `npm run typecheck` pass.
Sources
Open #405 · Per-address limits use each client's connecting address behind Next.js in the timeline