feat: MenuNav layer for the SummerCMS menu API
- typed client and useMenu/useMenuApi (SSR, menu:<code>:<locale> key, server and public bases, x-forwarded-for forwarded also on cached renders) - MenuNav and recursive MenuNavItem: WAI disclosure navigation, URL allowlist with a text fallback, rel on _blank, active link and trail, mobile toggle, Esc / focus-out / outside pointer / route change closing - menu tokens and base CSS, README - node tests (link rules, client, server-rendered NavItem) and a playground SSR smoke against a fixture API
This commit is contained in:
17
server/plugins/menu-client-address.ts
Normal file
17
server/plugins/menu-client-address.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// Keeps the visitor's address available to route-cached SSR renders.
|
||||
//
|
||||
// An app rule such as `'/**': { swr }` renders cached pages from a copy of
|
||||
// the request without headers. The menu API throttles per client address,
|
||||
// so forwarding only the Nuxt peer would put every cache miss in one bucket.
|
||||
// The event context is shared with that copy, so the incoming
|
||||
// x-forwarded-for plus the peer address is recorded here, before the cached
|
||||
// handler runs, and useMenuApi forwards 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.menuForwardedFor = forwarded
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user