Request Store
Server-only access to the current request context — headers, params, and query string — outside of a React component.
getRequestStore() is the server-side counterpart to useRequest(). Where useRequest() is a React hook that can only be called inside a component, getRequestStore() has no such restriction — use it in utility functions, data-fetching helpers, and service layers that are called from server components.
It returns null when called outside an active request scope: in the browser, in tests, or after rendering has finished. Always guard the return value.
Basic usage
import { getRequestStore } from 'nukejs'
export async function getCurrentUser() {
const ctx = getRequestStore()
if (!ctx) return null
const token = ctx.headers['authorization']
if (!token) return null
return verifyToken(token)
}Call the helper from any server component without threading props down the tree:
import { getCurrentUser } from '../lib/auth'
export default async function Dashboard() {
const user = await getCurrentUser()
if (!user) return <p>Not logged in.</p>
return <h1>Welcome, {user.name}</h1>
}The RequestContext object
| Field | Type | Description |
|---|---|---|
url | string | Full URL with query string, e.g. /blog/hello?lang=en |
pathname | string | Path only, no query string, e.g. /blog/hello |
params | Record<string, string | string[]> | Dynamic route segments matched by the file-system router |
query | Record<string, string | string[]> | Query-string params. Multi-value keys become arrays. |
headers | Record<string, string> | All incoming request headers including cookie and authorization. Multi-value headers are joined with ', '. |
Unlike useRequest() on the client, the server-side store always contains the full set of headers — including cookie, authorization, and x-api-key. These are stripped before the context is embedded in the HTML document so they never reach the browser.
Forwarding auth headers
A common pattern is reading cookie or authorization in a shared fetch helper and forwarding them to an internal service:
import { getRequestStore } from 'nukejs'
export async function apiFetch(path: string) {
const ctx = getRequestStore()
const headers: Record<string, string> = {
'Content-Type': 'application/json',
}
if (ctx?.headers['cookie']) {
headers['cookie'] = ctx.headers['cookie']
}
const res = await fetch(`http://localhost:4000${path}`, { headers })
if (!res.ok) throw new Error(`API error ${res.status}`)
return res.json()
}import { apiFetch } from '../lib/api'
export default async function Profile() {
const user = await apiFetch('/me') // cookie forwarded automatically
return (
<main>
<h1>{user.name}</h1>
<p>{user.email}</p>
</main>
)
}Detecting locale from headers
Reading accept-language in a utility is a clean foundation for i18n without polluting component props:
import { getRequestStore } from 'nukejs'
const SUPPORTED = ['en', 'fr', 'de'] as const
type Locale = typeof SUPPORTED[number]
export function getLocale(): Locale {
const ctx = getRequestStore()
const fromQuery = ctx?.query.lang as string | undefined
if (fromQuery && SUPPORTED.includes(fromQuery as Locale)) {
return fromQuery as Locale
}
const header = ctx?.headers['accept-language'] ?? ''
const tag = header.split(',')[0]?.split('-')[0]?.trim().toLowerCase()
return (SUPPORTED.includes(tag as Locale) ? tag : 'en') as Locale
}Null safety
getRequestStore() returns null when called outside an active request — during module initialisation, in tests, or anywhere in client-side code. Use optional chaining or an explicit guard:
const ctx = getRequestStore()
// Optional chaining — returns undefined if ctx is null
const locale = ctx?.headers['accept-language'] ?? 'en'
// Explicit guard — return early when outside SSR
if (!ctx) return defaultValueAPI reference
| API | Description |
|---|---|
getRequestStore() | Returns the current RequestContext, or null outside an active SSR request. |
normaliseHeaders(raw) | Converts Node's IncomingMessage.headers to a flat Record<string, string>. Multi-value headers are joined with ', '. |
sanitiseHeaders(raw) | Same as normaliseHeaders but strips sensitive headers (cookie, authorization, proxy-authorization, set-cookie, x-api-key) before embedding in the HTML document. |