Cookie handling
@duplojs/http/cookie lets you read cookies sent by the client and send them back easily in responses.
It is useful when you want to:
- read a value from incoming cookies
- set a new cookie in a response
- ask the client to delete an existing cookie
With cookiePlugin
import { createHub, ResponseContract, useRouteBuilder } from "@duplojs/http";
import { cookiePlugin } from "@duplojs/http/cookie";
import { DPE } from "@duplojs/utils";
const route = useRouteBuilder("GET", "/profile")
.extract({
cookies: {
session: DPE.string(),
},
})
.handler(
ResponseContract.noContent("profile.read"),
(floor, { response }) => response("profile.read")
.setCookie("last-route", "profile", {
httpOnly: true,
path: "/",
sameSite: "lax",
}),
);
const hub = createHub({ environment: "DEV" })
.plug(
cookiePlugin(),
)
.register(route);In this example:
- the plugin is registered once on the
Hub - every route registered in this
Hubthen benefits from input parsing and output serialization - the route extracts
sessiondirectly fromcookies - the handler also sends back a new cookie with
setCookie
This is the simplest approach when cookie support should be available across your whole application.
You can also pass your own parser and serializer to the plugin. This can be useful for signed cookies, custom encoding rules, or any project-specific format.
If you use cookiePlugin globally, you can exclude a specific route with IgnoreRouteCookieMetadata. This lets you keep the plugin enabled everywhere while automatically removing cookie hooks from some routes.
With hooks directly on one route
On a route, there are three ways to register cookie hooks:
- let
cookiePluginadd them automatically - add
cookieHooksto get input parsing and output serialization at once - add
parseRequestCookieHookandserializeResponseCookieHookseparately if you want more targeted behavior
If you want both behaviors directly on a route without using the plugin, cookieHooks is the simplest form.
import { createHub, ResponseContract, useRouteBuilder } from "@duplojs/http";
import { cookieHooks } from "@duplojs/http/cookie";
import { DPE } from "@duplojs/utils";
const route = useRouteBuilder("GET", "/admin/session", {
hooks: [
// defaultParser and defaultSerializer are use if nothing is given
cookieHooks(),
],
})
.extract({
cookies: {
session: DPE.string(),
},
})
.handler(
ResponseContract.ok(
"admin.session.read",
DPE.object({
session: DPE.string(),
}),
),
({ session }, { response }) => response(
"admin.session.read",
{
session,
},
).setCookie("admin-session", session, {
httpOnly: true,
path: "/admin",
}),
);
const hub = createHub({ environment: "DEV" })
.register(route);Here, the route gets the standard plugin behavior, but only for itself. This is often the most practical form when you want to enable cookies route by route.
With the two hooks separately on one route
import { useRouteBuilder } from "@duplojs/http";
import { defaultParser, defaultSerializer, parseRequestCookieHook, serializeResponseCookieHook } from "@duplojs/http/cookie";
const route = useRouteBuilder("GET", "/admin/session", {
hooks: [
parseRequestCookieHook({
parser: defaultParser, // or custom parser
}),
serializeResponseCookieHook({
serializer: defaultSerializer, // or custom serializer
}),
],
}); // ...This form is the most flexible. It is useful when you only want one hook, or when input parsing and output serialization should be handled separately.
