Nitro's cached handler renders from a header-less copy of the request, so under swr route rules useJournalApi, /rss.xml and the sitemap source forwarded only the Nuxt peer and every cache miss shared one Journal API rate-limit bucket (deferred in Phase 16). A Nitro plugin records x-forwarded-for plus the peer in event.context.journalForwardedFor on the request hook; the three callers forward it. Same key as the host app's workaround, which keeps working. The acme SSR smoke's x-forwarded-for check on the now route-cached playground is the test.
21 lines
1.1 KiB
TypeScript
21 lines
1.1 KiB
TypeScript
// Keeps the visitor's address available to route-cached SSR renders.
|
|
//
|
|
// An app rule such as `'/**': { swr }` wraps the page renderer (and any
|
|
// matching server route) in Nitro's cached handler, which renders from a copy
|
|
// of the request that carries no headers (only `varies` headers survive, so a
|
|
// cached page never depends on one visitor's request). Reading
|
|
// x-forwarded-for there would forward only the Nuxt peer, and every cache
|
|
// miss would share the Journal API's rate-limit bucket. The event context is
|
|
// shared with that copy, so the incoming x-forwarded-for plus the peer
|
|
// address is recorded on the request hook, before the cached handler runs;
|
|
// useJournalApi, /rss.xml and the sitemap source forward it.
|
|
|
|
export default defineNitroPlugin((nitroApp) => {
|
|
nitroApp.hooks.hook('request', (event) => {
|
|
const forwarded = [getRequestHeader(event, 'x-forwarded-for'), event.node.req.socket?.remoteAddress]
|
|
.filter((v): v is string => typeof v === 'string' && v !== '')
|
|
.join(', ')
|
|
event.context.journalForwardedFor = forwarded
|
|
})
|
|
})
|