Context object. It is an immutable view of the incoming request plus a set of response-building helpers — Anvil’s replacement for Express’s mutation-heavy (req, res) pair. Import the type from anvil:
Request properties
The underlying Web-standard
Request object. Use this when you need access to APIs not exposed directly on Context, such as ctx.req.arrayBuffer() or ctx.req.signal.The HTTP method in uppercase, e.g.
"GET", "POST", "DELETE". Delegates to ctx.req.method.The URL pathname without the query string, e.g.
"/users/42". Equivalent to new URL(ctx.req.url).pathname.The request headers as a Web-standard
Headers object. Access individual headers with .get().Named path parameters captured from the route pattern. The keys correspond to the dynamic folder names in your For catch-all routes (
server/routes/ tree (without the brackets).[...param]), ctx.params.param contains the full remaining path joined with /:The URL query string parsed into a plain object. Repeated keys are collected into an array; single-occurrence keys are plain strings.The result is computed lazily on first access and cached for the lifetime of the request.
A mutable scratch space for passing data from middleware to the handler (or to a later middleware). Anvil does not touch this object — it is entirely yours to use.See Scoped Middleware for a full auth-guard example.
Body parsing
Parse the request body based on the If the body cannot be parsed (e.g., malformed JSON), Anvil throws an
Content-Type header:application/json→ parsed withJSON.parse(), returns the resulting valueapplication/x-www-form-urlencodedormultipart/form-data→ returns aFormDataobject- Anything else → returns the body as a plain
string
ctx.body() from both a middleware and the handler is safe and reads the stream only once.HttpError(400, 'Malformed request body') automatically.Response helpers
All response helpers accept an optionalinit parameter of type ResponseInit (the same second argument as the Web Response constructor) for setting status codes and custom headers.
Serialize
data to JSON and return a Response with Content-Type: application/json. Delegates to Response.json().Return a
Response with Content-Type: text/plain; charset=utf-8.Return a
Response with Content-Type: text/html; charset=utf-8.Return a redirect response.
status defaults to 302. Use 301 for a permanent redirect.Return a streaming response. Pass a
ReadableStream as the body — useful for server-sent events, large file transfers, and AI model output.Throwing HTTP errors
UseHttpError (imported from anvil) to throw an HTTP error from a handler or middleware. Anvil’s kernel catches it and converts it to a structured JSON error response automatically.
The HTTP status code. 4xx errors expose their message to the client by default; 5xx errors do not (the client sees the generic status message instead).
The error message. For 4xx errors, this is sent to the client. For 5xx errors, it is hidden in production and only visible in dev mode (
NODE_ENV !== 'production').Optional additional data included in the
details field of the JSON response. Only sent to the client when expose is true (the default for 4xx errors).Override the default expose behaviour. Set to
true to force the message and details onto a 5xx response in development, or false to hide them on a 4xx.The underlying error that caused this
HttpError. Forwarded as the standard Error.cause property — visible in stack traces but never sent to the client.Full handler example
Here is a handler that demonstrates multipleContext features together:
server/routes/users/[id]/get.ts