Whats the point of composing middleware in Koa?

KoaJS uses koa-compose underneath (here), so app.use(compoase([m1,m2])); and app.use(m1); app.use(m2); are the same. Using koa-compose explicitly can give more power for customization. Following is one such case:

Adding middlewares through app.use(middleware), will cause all of the middlewares to be executed upon each request in the specified order. But if you want to selectively run different set of middlewares for each route (or in a different order), you can use explicitly use koa-compose to create specialized middleware stacks for each route.

var app = require('koa')();
var router = require('koa-router')();
var compose = require('koa-compose');

var allMiddlewares = compose([m1,m2,m3]);

router.get('/', allMiddlewares);
// selectively enable logging middleware for this route
router.get('/test', compose(logger, allMiddlewares));

app
  .use(router.routes())
  .use(router.allowedMethods());

I had the same questions of why we need to use koa-compose, since koa itself can handle multiple middlewares. But recently I have been working on the authentication part of my koa server.

I have to check if user is authenticated and sometimes I need to check if user role meets the requirement. In that case, I have two middlewares one is called isAuthenticated, another is hasRoles

Some routes expose to any user that is authenticated, so I can do

.get('/', auth.isAuthenticated, handler())

But for routes need to check if user role meets the requirement, I need to do

.get('/', auth.isAuthenticated, auth.hasRole('admin'), handler())

When I have other authentication middlewares, the middlewares I put in the route becomes pretty long. I am benefited by using koa-compose, since in my case I can chain the isAuthenticated and hasRoles middlewares together.

requiresRole(role) {
    return compose([isAuthenticated, hasRole(role)])
}

.get('/', auth.requiresRole('admin'), handler())

It's neat and less errors.

Tags:

Koa