The Context Object

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.

4 min read Level 1/5 #koa#context#ctx
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:

AliasDelegates toDescription
ctx.methodctx.request.methodHTTP verb, e.g. "GET"
ctx.urlctx.request.urlFull URL including query string
ctx.pathctx.request.pathPathname without query string
ctx.queryctx.request.queryParsed query string as an object
ctx.bodyctx.response.bodyResponse body to send
ctx.statusctx.response.statusHTTP status code
ctx.typectx.response.typeContent-Type shorthand
ctx.headers / ctx.headerctx.request.headersIncoming 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.

The Request Object →