Whats the point of composing middleware in Koa?
Asked Answered
T

2

11

I am diving into Koa2 and I see koa-compose. I get that I give it middlewares and it returns one, but why? What is the benefit of having multiple middleware wrapped as one instead of just adding them separately?

app.use(compose(m1, m2))

vs:

app.use(m1)
app.use(m2)
Toilsome answered 28/8, 2016 at 0:1 Comment(0)
H
17

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());
Holub answered 28/8, 2016 at 4:29 Comment(7)
Are you saying the sole purpose of koa-compose is to organize middleware in sets so that I can essentially type less? If not I would like to see an example as I am not clear on its benefit.Toilsome
@Yashua No koa-compose as its name is used to compose a set of middleware into a single middleware. How and where you use depends on the specific scenario. Above is just one possible scenario.Holub
I apologize for being dense. What would then be an example of where I would have to use it - i.e. where I could not use separate middleware?Toilsome
@Yashua In your example, both are the same as Koa uses koa-compose underneath.Holub
Thanks. It is indeed just an organization feature as I thought.Toilsome
@Holub I think compose() takes an array of middleware, so your examples compose(m1,m2,m3) should actually be compose([m1,m2,m3])?Leavings
Sorry to chime in late here but I just found this library and it suits my need perfectly. I'm trying to create a set of standard middle wares for my team to use. I can use this to "compose" them into a single middleware that I can export as a library that anyone can include and have all our apps start from a common baseline.Joacima
G
8

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.

Gustafsson answered 23/5, 2018 at 6:15 Comment(1)
Hey , im in a similar situation and i have tiny question .. how do i get the results of the isauthenticated or requiresrole into my handlerNadenenader

© 2022 - 2024 — McMap. All rights reserved.