Skip to content

Headers and cookies

Setting response headers and cookies during a render.

Updated View as Markdown

Reading

Anywhere in a server component or action:

import { headers, cookies, searchParams } from '@rsc-kit/core/request'

export default async function Page() {
  const h = await headers()
  const jar = await cookies()

  return <p>Hello {jar.get('name')?.value ?? 'stranger'}</p>
}

Writing

import { responseHeaders, cookies } from '@rsc-kit/core/request'

export async function middleware() {
  responseHeaders().set('X-Frame-Options', 'DENY')

  const jar = await cookies()
  jar.set('last-seen', new Date().toISOString(), { httpOnly: true, path: '/' })
}

Writing only works in middleware. Middleware runs before the render, while the response line has not been sent yet. A component runs during streaming, when the headers are already on the wire — writing from one throws rather than being silently dropped, so you find out immediately.

A redirect carries them too, which is what lets middleware remember where someone was going before sending them to log in:

export async function middleware() {
  const jar = await cookies()

  if (!jar.get('session')) {
    jar.set('intended', '/dashboard', { path: '/' })
    redirect('/login')
  }
}
jar.set('name', 'value', {
  httpOnly: true,
  secure: true,
  sameSite: 'lax',      // 'strict' | 'lax' | 'none'
  path: '/',
  maxAge: 60 * 60 * 24,
  expires: new Date('2027-01-01'),
})

Names are validated as cookie tokens and sameSite / expires are checked, so a typo is an error rather than a header the browser quietly ignores.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close