Skip to main content

Cookies

OPRA parses incoming cookies automatically and makes them available on ctx.cookies. Outgoing cookies are set via ctx.response.cookie(). Expected request cookies can be declared on the operation so they appear in the API schema.


Reading request cookies

ctx.cookies

The parsed cookie map for the current request. Values are strings unless the cookie was serialized as JSON (in which case the adapter deserializes it automatically).

const sessionId = ctx.cookies['session-id'];
const lang = ctx.cookies['preferred-lang'] ?? 'en';

ctx.cookies is a convenience alias for ctx.request.cookies.


Declaring expected request cookies

Use .Cookie() in the operation decorator chain to declare a cookie parameter. Declared cookies appear in the API schema and support the same options as other parameter types.

@(HttpOperation.GET()
.Cookie('session-id', { type: 'string', required: true })
.Cookie('preferred-lang', 'string')
.Response(200, { type: Customer }))
async get(ctx: HttpContext) {
const sessionId = ctx.cookies['session-id'];
const lang = ctx.cookies['preferred-lang'] ?? 'en';
// ...
}

.Cookie() options:

OptionTypeDescription
typeType | stringOPRA type for the cookie value.
requiredbooleanWhether the cookie must be present.
defaultanyDefault value when the cookie is absent.
deprecatedboolean | stringMark the cookie as deprecated.
descriptionstringHuman-readable description for the schema.

Setting response cookies

ctx.response.cookie(name, value, options?)

cookie(name: string, value: any, options?: CookieOptions): this

Appends a Set-Cookie header to the response. Returns this for chaining.

ctx.response.cookie('session-id', token, {
httpOnly: true,
secure: true,
maxAge: 3_600_000, // 1 hour in ms
sameSite: 'strict',
path: '/',
});

Object values are serialized to JSON automatically. Signed cookies require options.signed: true and a secret.

ctx.response.clearCookie(name, options?)

clearCookie(name: string, options?: CookieOptions): this

Expires the cookie immediately. The path defaults to / when omitted. Pass the same domain and path used when the cookie was set to ensure the browser deletes the right cookie:

ctx.response.clearCookie('session-id', { path: '/' });

OptionTypeDescription
maxAgenumberExpiry in milliseconds from now. Converted to an Expires date and a Max-Age value (in seconds) on the header.
expiresDateExplicit expiry date. Takes precedence over maxAge.
httpOnlybooleanWhen true, the cookie is inaccessible to client-side JavaScript.
securebooleanWhen true, the cookie is sent only over HTTPS.
sameSite'strict' | 'lax' | 'none' | booleanControls cross-site sending. 'none' requires secure: true.
pathstringCookie path scope. Defaults to '/'.
domainstringCookie domain scope.
signedbooleanSign the value with secret. The adapter prefixes the value with s:.
secretstringSecret used for signing. Falls back to req.secret if not provided here.
encode(val: string) => stringCustom encoding function for the cookie value.

Complete example

import { HttpController, HttpOperation } from '@opra/common';
import { HttpContext } from '@opra/http';

@HttpController({ path: 'auth' })
export class AuthController {
@(HttpOperation.POST({ path: 'login' })
.RequestContent({ type: LoginDto })
.Response(200))
async login(ctx: HttpContext) {
const { email, password } = await ctx.getBody<LoginDto>();
const token = await this.authService.createSession(email, password);

ctx.response.cookie('session', token, {
httpOnly: true,
secure: true,
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
sameSite: 'strict',
path: '/',
});
}

@(HttpOperation.POST({ path: 'logout' })
.Cookie('session', { type: 'string', required: true })
.Response(204))
async logout(ctx: HttpContext) {
const token = ctx.cookies['session'];
await this.authService.revokeSession(token);
ctx.response.clearCookie('session', { path: '/' });
}

@(HttpOperation.GET({ path: 'me' })
.Cookie('session', { type: 'string', required: true })
.Response(200, { type: User }))
async me(ctx: HttpContext) {
return this.authService.getUserBySession(ctx.cookies['session']);
}
}

Headers · Reading the Request Body · Sending Responses