How do I combine Connect middleware into one middleware?

Express accepts arrays for app.use if you have a path:

var middleware = [connect.urlencoded(), connect.json()];
app.use('/', middleware)

However, if you want a generic combineMiddleware function, you can build a helper easily without any additional libraries. This basically takes advantage of the fact that next is simply a function which takes an optional error:

/**
 * Combine multiple middleware together.
 *
 * @param {Function[]} mids functions of form:
 *   function(req, res, next) { ... }
 * @return {Function} single combined middleware
 */
function combineMiddleware(mids) {
  return mids.reduce(function(a, b) {
    return function(req, res, next) {
      a(req, res, function(err) {
        if (err) {
          return next(err);
        }
        b(req, res, next);
      });
    };
  });
}

If you like fancy stuff, here is one of possible solutions:

var connect = require('connect')
var app = connect()

function compose(middleware) {
  return function (req, res, next) {
    connect.apply(null, middleware.concat(next.bind(null, null))).call(null, req, res)
  }
}

function a (req, res, next) {
  console.log('a')
  next()
}

function b (req, res, next) {
  console.log('b')
  next()
}

app.use(compose([a,b]))

app.use(function (req, res) {
  res.end('Hello!')
})

app.listen(3000)

Here is what it does: compose function takes array of middleware and return composed middleware. connect itself is basically a middleware composer, so you can create another connect app with middlewares you want: connect.apply(null, middleware). Connect app is itself a middleware, the only problem is that it doesn't have a next() call in the end, so subsequent middleware will be unreachable. To solve that, we need another last middleware, which will call next : connect.apply(null, middleware.concat(last)). As last only calls next we can use next.bind(null, null) instead. Finally, we call resulting function with req and res.


Old question, but the need is still frequent for all the things using middlewares, like connect, express or custom made req/res/next patterns.

This is a very elegant and purely functional solution:

File ./utils/compose-middleware.js:

function compose(middleware) {
  if (!middleware.length) {
    return function(_req, _res, next) { next(); };
  }

  var head = middleware[0];
  var tail = middleware.slice(1);

  return function(req, res, next) {
    head(req, res, function(err) {
      if (err) return next(err);
      compose(tail)(req, res, next);
    });
  };
}

module.exports = compose;

The final result of the compose(middlewareList) is a single middleware that encapsulates the whole chain of middleware initially provided.

Then simply import it and use like this:

File app.js:

var connect = require('connect');
var compose = require('./utils/compose-middleware');

var middleware = compose([
  connect.urlencoded(),
  connect.json()
]);

var app = connect();
app.use(middleware);