- privateRevalidate sets max-age=0 on cache-control values with s-maxage - server/plugins/journal-revalidate.ts wraps res.setHeader per request, so Nitro's 200 and h3's 304 answers both carry it - purge-check: max-age=0 on 200 and 304, purged _payload.json, a second purge after re-caching, X-Real-IP refused, 404 on a server without a token - README: cachePurgeToken row and a Site cache purge section
30 lines
1.4 KiB
TypeScript
30 lines
1.4 KiB
TypeScript
// Browser revalidation of route-cached pages. Nitro's route cache answers
|
|
// 200 with `cache-control: s-maxage=<n>, stale-while-revalidate`, which
|
|
// gives browsers no max-age, so they apply heuristic freshness from
|
|
// Last-Modified; a conditional request it answers 304 with
|
|
// `public, max-age=<n>, s-maxage=<n>`, so after one revalidation a browser
|
|
// could reuse its copy for the whole TTL, past any site cache purge.
|
|
//
|
|
// This plugin passes every cache-control value a response sets through
|
|
// privateRevalidate: values with s-maxage get max-age=0, so browsers ask on
|
|
// each view (a cheap 304 while the page is unchanged) and shared caches keep
|
|
// s-maxage. The 304 path ends the response before any beforeResponse hook
|
|
// runs, so the rewrite wraps the request's res.setHeader instead. Static
|
|
// assets carry no s-maxage and are untouched.
|
|
|
|
import { privateRevalidate } from '../../app/utils/siteCache.ts'
|
|
|
|
export default defineNitroPlugin((nitroApp) => {
|
|
nitroApp.hooks.hook('request', (event) => {
|
|
const res = event.node.res
|
|
const setHeader = res.setHeader
|
|
res.setHeader = function (name, value) {
|
|
if (typeof name === 'string' && name.toLowerCase() === 'cache-control') {
|
|
if (typeof value === 'string') value = privateRevalidate(value)
|
|
else if (Array.isArray(value)) value = value.map((v) => privateRevalidate(String(v)))
|
|
}
|
|
return setHeader.call(this, name, value)
|
|
} as typeof res.setHeader
|
|
})
|
|
})
|