ctx Merges Request and Response Into One Convenient Handle
The Context Object
Koa's ctx object is the single argument every middleware receives. It delegates to ctx.request and ctx.response and provides helpers like ctx.throw and ctx.assert.
What you'll learn
- Read and write common ctx aliases like ctx.body, ctx.status, and ctx.url
- Use ctx.state to pass data between middleware functions
- Handle errors with ctx.throw and ctx.assert
Every Koa middleware receives a single ctx argument. It combines everything
you would normally find split across Node’s req and res objects, plus
Koa-specific helpers.
Delegated Aliases
Most properties on ctx are shortcuts that delegate to ctx.request or
ctx.response:
| Alias | Delegates to | Description |
|---|---|---|
ctx.method | ctx.request.method | HTTP verb, e.g. "GET" |
ctx.url | ctx.request.url | Full URL including query string |
ctx.path | ctx.request.path | Pathname without query string |
ctx.query | ctx.request.query | Parsed query string as an object |
ctx.body | ctx.response.body | Response body to send |
ctx.status | ctx.response.status | HTTP status code |
ctx.type | ctx.response.type | Content-Type shorthand |
ctx.headers / ctx.header | ctx.request.headers | Incoming request headers |
Reading ctx.body in middleware is uncommon — ctx.body is a write target
for the response. For the request body you will use a body-parsing middleware
(covered in Chapter 2).
ctx.state — Sharing Data Between Middleware
ctx.state is a plain object reserved for passing information between
middleware layers. It is the right place to attach things like the
authenticated user or feature flags:
app.use(async (ctx, next) => {
ctx.state.requestId = crypto.randomUUID();
await next();
});
app.use(async (ctx) => {
ctx.body = { id: ctx.state.requestId };
}); ctx.app — Back Reference
ctx.app is a reference to the Koa application instance, useful inside
middleware when you need app.keys or other app-level settings without
importing the app module directly.
ctx.throw — Send an HTTP Error
app.use(async (ctx) => {
if (!ctx.query.token) {
ctx.throw(401, "Missing token");
}
ctx.body = "Authenticated!";
}); ctx.throw(status, message) creates and throws an HttpError. Koa catches it
and responds with the given status code.
ctx.assert — Guard with a Condition
ctx.assert is like ctx.throw but only throws when a condition is falsy —
modelled after Node’s built-in assert:
app.use(async (ctx) => {
ctx.assert(ctx.query.id, 400, "id is required");
ctx.body = `Fetching item ${ctx.query.id}`;
}); Up Next
Take a closer look at everything available on ctx.request.