Set HTTP response headers from anywhere during server-side rendering - loaders, components, or middleware. Headers are accumulated and merged onto the final response.
import { setResponseHeaders } from 'one'
await setResponseHeaders((headers) => {
headers.set('X-Custom-Header', 'value')
})
The headers parameter is a standard Headers object.
Use setResponseHeaders in loaders to enable CDN caching and Incremental Static Regeneration:
app/blog/[slug]+ssr.tsx
import { setResponseHeaders, useLoader } from 'one'
export async function loader({ params }) {
await setResponseHeaders((headers) => {
headers.set('Cache-Control', 'public, s-maxage=3600, stale-while-revalidate=86400')
})
const post = await fetchPost(params.slug)
return { post }
}
export default function BlogPost() {
const { post } = useLoader(loader)
return <article>{post.content}</article>
}
Common cache header patterns:
s-maxage=3600 - CDN caches for 1 hourstale-while-revalidate=86400 - Serve stale content while revalidating in background (up to 1 day)max-age=0, must-revalidate - Always revalidate with originprivate, no-store - Never cache (for user-specific data)Note: stale-while-revalidate requires CDN support (Vercel, CloudFront, Fastly). Cloudflare does not currently support it.
Set cookies using the standard Set-Cookie header:
app/auth/login+api.ts
import { setResponseHeaders } from 'one'
export async function POST(request: Request) {
const { token } = await authenticateUser(request)
await setResponseHeaders((headers) => {
headers.append('Set-Cookie', `session=${token}; HttpOnly; Secure; SameSite=Strict; Path=/`)
})
return Response.json({ success: true })
}
app/_middleware.ts
import { createMiddleware, setResponseHeaders } from 'one'
export default createMiddleware(({ request }) => {
setResponseHeaders((headers) => {
headers.set('X-Request-Id', crypto.randomUUID())
})
})
Edit this page on GitHub.