Context
The request context object with headers, cookies, SSE, and timing.
Context
The Context object (ctx) is passed to every route handler and middleware. It wraps the native Request and provides utilities for managing state, parameters, responses, cookies, request IDs, server timing, and server-sent events.
Properties
ctx.req
The native Request object.
ctx.body
The parsed request body. If you use validation schemas, this is strongly typed. Otherwise it defaults to any (parsed JSON or Form Data).
ctx.query
URL query parameters as an object.
// GET /search?q=bklar&page=2
app.get("/search", (ctx) => {
console.log(ctx.query.q); // "bklar"
console.log(ctx.query.page); // "2"
});ctx.params
Dynamic route parameters (e.g., /users/:id).
ctx.state
Shared mutable object for passing data between middlewares and handlers.
app.use(async (ctx, next) => {
ctx.state.user = { id: 1, role: "admin" };
await next();
});
app.get("/me", (ctx) => ctx.json(ctx.state.user));ctx.requestId
A unique ID for this request. Generated as UUID v4 by default, or extracted from the incoming X-Request-Id header. Included in all response headers automatically.
console.log(ctx.requestId); // "f47ac10b-58cc-4372-a567-0e02b2c3d479"ctx.signal
An AbortSignal that aborts when the request times out (if a route-level timeout is set) or is canceled by the client.
Response Helpers
| Helper | Description | Content-Type |
|---|---|---|
ctx.json(data, status?, headers?) | JSON response | application/json |
ctx.text(data, status?, headers?) | Plain text response | text/plain |
ctx.status(code, headers?) | Empty response with status | — |
ctx.download(file, filename?, headers?) | File download | auto-detected |
ctx.sse() | Server-Sent Events stream | text/event-stream |
Every response helper automatically appends X-Request-Id and Server-Timing headers when applicable.
Cookies
// Read
const session = ctx.getCookie("session_id");
// Write
ctx.setCookie("theme", "dark", {
httpOnly: true,
maxAge: 3600,
path: "/",
secure: true,
sameSite: "Lax",
});Server Timing
Record timing entries that appear in the Server-Timing response header:
app.get("/users", async (ctx) => {
const users = await ctx.time("db", () => db.findUsers());
return ctx.json(users);
});SSE (Server-Sent Events)
Stream events to the client:
app.get("/events", (ctx) => {
const sse = ctx.sse();
sse.send("message", JSON.stringify({ text: "hello" }));
sse.close();
return undefined;
});See the SSE documentation for full details on server-sent events.