How do I combine Connect middleware into one middleware?

middleware, node.js, node.js-connect

Solution

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`.

Problem

I have a few middlewares that I want to combine into one middleware. How do I do that? For example: ``` // I want to shorten this... app.use(connect.urlencoded()) app.use(connect.json()) // ...into this: app.use(combineMiddleware([connect.urlencoded, connect.json])) // ...without doing this: app.use(connect.urlencoded()).use(connect.json()) ``` I want it to work dynamically -- I don't want to depend on which middleware I use. I feel like there's an elegant solution other than a confusing `for` loop.

Original source