Context
Every handler and middleware receives a context object as its only argument. It is conventionally named ctx. The context carries the request, a few derived properties, the typed route params, the state set by middleware, and a small number of helpers.
export const handlers = handler((ctx) => {
ctx.req; // the Request
ctx.url; // the parsed URL
ctx.params; // route params
ctx.state; // shared state from middleware
return { data: null };
});Properties
| Property | Type | Description |
|---|---|---|
req |
Request |
The incoming request. Read the body with req.formData(), req.json(), and so on. |
url |
URL |
req.url parsed once. Read the path with url.pathname and the query with url.searchParams. |
params |
Record<string, string> |
Route parameters, typed from the file’s [bracket] segments. |
state |
S |
Shared state, typed from the closest _middleware. |
error |
unknown |
The thrown value. Only set when the route was reached via the error page. |
isPartial |
boolean |
true for a client-driven partial navigation. |
runtime |
RuntimeContext | undefined |
Deployment-target request context (a host’s bindings or env). undefined when the host provides none. |
Reading request data
Reading the body, the query string, and headers is plain Fetch API. The context is just a thin layer over a normal Request.
export const handlers = handler({
async POST(ctx) {
const form = await ctx.req.formData(); // form submissions
const body = await ctx.req.json(); // JSON body
const q = ctx.url.searchParams.get("q"); // ?q=
const auth = ctx.req.headers.get("authorization");
// ...
return { data: null };
},
});Methods
redirect(pathOrUrl, status?)
Builds a redirect Response. The default status is 302. Pass 303 after a form POST. Pass 307 or 308 to preserve the method.
return ctx.redirect("/dashboard"); // 302
return ctx.redirect("/login", 303); // after a POSTProtocol-relative paths like //evil.com/x are collapsed to a single /. This means a trusted path coming from your own code can’t be turned into a cross-origin redirect by user-supplied input.
next(state?)
Available on middleware only. Calls the next middleware in the chain, or the route handler if this is the last one. Middleware uses it to continue the chain and to pass state forward.
export default middleware((ctx) => {
return ctx.next({ ...ctx.state, user: getUser(ctx.req) });
});waitUntil(promise)
Hands the host a promise that should keep the invocation alive past the response. Use it for logging, analytics, or cache writes that should not block the response itself.
ctx.waitUntil(logAnalytics(ctx.req));On hosts without a native waitUntil (Node in dev, for example), the promise still runs. It just isn’t tracked.