docs(19.3-06): pair a remote purge URL with the site's allowProxied (WR-03)
- caching.md: an https purge_url on another host goes through the site's proxy; set NUXT_SITE_CACHE_ALLOW_PROXIED=true there, the token is then the only gate - cooler README: the purge_url row points at it
This commit is contained in:
@@ -168,7 +168,11 @@ The Nuxt layers of the core plugins (the Journal, menu and FAQ layers) each ship
|
||||
|
||||
- `POST /api/__site__/cache/purge` removes every entry of Nitro's route cache (pages, their `_payload.json` and feeds) and answers `{"purged": <n>}`.
|
||||
- Its token is `runtimeConfig.siteCache.purgeToken`, set through `NUXT_SITE_CACHE_PURGE_TOKEN` to the same value as `site_cache.purge_token`. With a token shorter than 32 characters the route answers 404.
|
||||
- It answers 404 to any request that came through a reverse proxy (`X-Forwarded-For`, `X-Real-IP` or `Forwarded`) and 401 to a missing or wrong bearer token, compared in constant time.
|
||||
- It answers 404 to any request that came through a reverse proxy (`X-Forwarded-For`, `X-Real-IP` or `Forwarded`), unless the site opts in with `NUXT_SITE_CACHE_ALLOW_PROXIED` (see [A purge URL on another host](#a-purge-url-on-another-host)), and 401 to a missing or wrong bearer token, compared in constant time.
|
||||
- Each layer also ships the route rule `'/api/__site__/**': { cache: false }`. Without it, a site rule such as `'/**': { swr: 300 }` would wrap the purge route in Nitro's cached handler, which answers from the cache without running the route.
|
||||
|
||||
The three copies are byte-identical, so it does not matter which layer's copy Nitro picks.
|
||||
|
||||
### A purge URL on another host
|
||||
|
||||
When the site does not run on the backend's machine, `site_cache.purge_url` is an https URL on the site's host, for example `https://www.example.com/api/__site__/cache/purge`. The request then reaches Nuxt through the site's TLS-terminating proxy (nginx, Caddy, Traefik), which adds `X-Forwarded-For`, `X-Real-IP` or `Forwarded`, and the route refuses such requests by default with 404. Pair the https purge URL with `NUXT_SITE_CACHE_ALLOW_PROXIED=true` on the site (`runtimeConfig.siteCache.allowProxied`): the route then accepts proxied requests, and the bearer token is the only gate. Keep the token long and secret (the same value in `site_cache.purge_token` and `NUXT_SITE_CACHE_PURGE_TOKEN`), and keep the default, loopback and no flag, whenever the site runs next to the backend.
|
||||
|
||||
@@ -36,7 +36,7 @@ Use cases:
|
||||
- Keys carry a per-application prefix: `cache.prefix`, or by default `app.name` lower-cased with every run of other characters than `a-z` and `0-9` replaced by `_`, then `:` (`summer:` when `app.name` is empty). Cache keys are `<prefix>cache:<key>`, rate-limit keys `<prefix>rl:<key>`.
|
||||
- `cooler.OpenRedis` accepts `redis://`, `rediss://` (TLS) and `unix://` URLs, does not dial at construction, and skips the `CLIENT SETINFO` and maintenance-notification handshakes.
|
||||
- Only `serve` installs cooler: `route:list` and `surf.Assemble` in tests keep the in-process store and never dial Redis.
|
||||
- Site-cache purge: `cooler.SiteCachePurger` sends `POST {"kind":…,"slug":…}` with `Authorization: Bearer <token>` to `site_cache.purge_url`. `cooler.PurgeSiteCacheAfterCommit` queues that request on the save transaction through `lagoon.AfterCommit`, so it is queued only after the save commits and never for a save that rolled back. The save never waits for the site: a per-purger worker sends the request, with at most one in flight, and saves committed meanwhile collapse into one follow-up request (each purge clears the site's whole route cache), so a bulk delete sends at most two. `cooler.SiteCachePurger.Wait` drains the queue for tests and commands, and `cooler.Handle.Close` drains it at shutdown.
|
||||
- Site-cache purge: `cooler.SiteCachePurger` sends `POST {"kind":…,"slug":…}` with `Authorization: Bearer <token>` to `site_cache.purge_url`. `cooler.PurgeSiteCacheAfterCommit` queues that request on the save transaction through `lagoon.AfterCommit`, so it is queued only after the save commits and never for a save that rolled back. The save never waits for the site: a per-purger worker sends the request, with at most one in flight, and saves committed meanwhile collapse into one follow-up request (each purge clears the site's whole route cache), so a bulk delete sends at most two. The purger's `Wait` method drains the queue for tests and commands (see the API reference), and `cooler.Handle.Close` drains it at shutdown.
|
||||
- A purge never fails a save: each request is bounded by `cooler.SiteCachePurgeTimeout` (2 s) and detached from the request's cancellation, and a failure, an error status or a timeout is one warning (`cooler: site cache purge failed`) with the kind, slug and status. A success is one info line (`cooler: site cache purged`) with the purged count the site answered. Log lines and errors never carry the token or the full URL.
|
||||
- The purge URL must be http or https with a host and without user info or a fragment; plain http is accepted only for a loopback host (127.0.0.0/8, `::1`, `localhost`), so the token never crosses a network in clear. The token needs at least `cooler.SiteCachePurgeMinTokenLength` (32) characters, the same minimum the site's route applies. Setting only one of the two keys, or an invalid value, fails `serve` at boot with an error that names the key.
|
||||
- `cooler.Install` publishes the purger at boot unless a plugin already published one (a plugin that still reads its own deprecated keys), and `cooler.SiteCacheFromApp` gives admin hooks the same purger lazily in commands and tests that do not run `serve`. Plugins take the save transaction from `cabana.TxFromContext` themselves; cooler imports neither surf nor cabana.
|
||||
@@ -204,7 +204,7 @@ func AllowExport(ctx context.Context, app *backpack.App, fallback cooler.Attempt
|
||||
| `http.rate_limit.store` | `memory` | Where `throttle` counters live: `memory` (per instance) or `redis` (shared). Any other value fails at boot. Environment: `SUMMER_HTTP__RATE_LIMIT__STORE`. |
|
||||
| `redis.url` | none | Redis URL (`redis://`, `rediss://` or `unix://`). Required when a Redis cache or rate-limit store is selected; keep it in the environment when it carries a password. Environment: `SUMMER_REDIS__URL`. |
|
||||
| `cache.prefix` | from `app.name` | Prefix of every cooler key. Environment: `SUMMER_CACHE__PREFIX`. |
|
||||
| `site_cache.purge_url` | none | The host site's purge route, for example `http://127.0.0.1:3000/api/__site__/cache/purge`. http only to a loopback host, https otherwise. Set together with the token, or neither (no purge). Environment: `SUMMER_SITE_CACHE__PURGE_URL`. |
|
||||
| `site_cache.purge_url` | none | The host site's purge route, for example `http://127.0.0.1:3000/api/__site__/cache/purge`. http only to a loopback host, https otherwise; an https URL on another host goes through the site's proxy, so the site sets `NUXT_SITE_CACHE_ALLOW_PROXIED=true` (see [A purge URL on another host](../../docs/services/caching.md#a-purge-url-on-another-host)). Set together with the token, or neither (no purge). Environment: `SUMMER_SITE_CACHE__PURGE_URL`. |
|
||||
| `site_cache.purge_token` | none | Bearer token of the purge request, at least 32 characters, the same value as the site's `NUXT_SITE_CACHE_PURGE_TOKEN`. Keep it in the environment. Environment: `SUMMER_SITE_CACHE__PURGE_TOKEN`. |
|
||||
|
||||
## Dependencies
|
||||
|
||||
Reference in New Issue
Block a user