middleware

Passing Information Through Koa Middleware Via "this.state"

Koa has a context object created during every request/response cycle. The context is referenced via this in the middleware. Much information are captured in the context, such as req and res. In order to avoid polluting the context and colliding with other middleware, the information from your application should be encapsulated into this.state property, a namespace for passing information through middleware during request/response cycle:

1
2
3
4
5
6
7
8
9
10
11
12
require('koa')().use(function *(next) {
var state = this.state;
state.user = yield users.create(this.request.body);
state.code = 201;
state.body = {
name: user.name,
mail: user.mail
};
yield next;
}).listen(3000);

The this.state has been initialized into an empty object:

1
2
3
require('koa')().use(function *(next) {
this.body = this.state;
}).listen(3000);

Therefore, we can start using it right away without doing our own initialization:

1
2
3
4
5
6
7
$ http :3000
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 2
Content-Type: application/json; charset=utf-8
{}

Use Array of Middleware in Koa Router

Koa Router v4.2 does not support an array of middleware, multiple middleware must be entered one by one:

1
app.get('/foo', middleware1, middleware2);

Using an array is much cleaner than multiple arguments.

1
app.get('/foo', [middleware1, middleware2]);

But the above will throw error:

1
Error: GET: `middleware` must be a function, not `object`

This can be easily fixed by using Koa Compose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var app = require('koa')();
var router = require('koa-router');
var compose = require('koa-compose');
app.use(router(app));
app.get('/foo', compose([
function *(next) {
this.body = {};
yield next;
},
function *(next) {
this.body.foo = 'foo';
yield next;
},
function *(next) {
this.body.bar = 'bar';
yield next;
}
]));

Hence:

1
app.get('/foo', compose([middleware1, middleware2]));