Express routes middleware chains

I have worked with node.js for two years now, and have enjoyed every bit of it. It wasn't an easy switch from Java but with help available in plenty, I wasn't going to be worried at all. Here's an article from Tomas "wereHamster" Carnecky that helped me learn middlewares in express apps.

Express routes middleware chains

In a web server each route handler usually has a single success and multiple failure cases. If we ignore all the failure cases we can reduce the handler to just a single line of code. Here is an example:

app.get '/home', (req, res) ->
  res.render 'home'

But most handlers are more complex than that, they need to fetch data from a database, validate input etc. These things can fail and we need to handle that. You could add this logic to the route handler, but especially with the asynchronous nature of nodejs, it would soon make your handlers unreadable. Here we fetch just two models from the database and already have four levels deep nesting:

app.get '/book/:book', (req, res) ->
  Book.fetch req.param('book'), (err, book) ->
    if err
      res.render '404'
    else
      Author.fetch book.author, (err, author) ->
        if err
           res.render '500'
        else
           res.render 'book', { book, author }

Thankfully experessjs gives us route middleware which we can use to keep the route handler a single line of code no matter how complex the logic is. Let's see how our code looks if we mode all the logic into route middleware:

fetchBook = (req, res, next) ->
  Book.fetch req.param('book'), (err, book) ->
    if err
      res.render '404'
    else
      req.book = book; next()

fetchBookAuthor = (req, res, next) ->
  Author.fetch req.book.author, (err, author) ->
    if err
      res.render '500'
    else
      req.author = author; next()

app.get '/book/:book, fetchBook, fetchBookAuthor, (req, res) ->
  res.render 'book', { book: req.book, author: req.author }

Even just looking at the route definition is pure joy: when a request comes in to /book/something, first call fetchBook, then fetchBookAuthor, and finally render the book template. Errors are handled in the middleware functions as soon as they occur, so we don't have to worry about them.

This is a rather simple example with just two middleware functions. But what if you have to check permissions, validate the input etc? I can easily imagine having dozens of middleware functions. This way you can structure your logic so that the code is never more than one or two levels of nesting deep, and that helps to keep the code comprehensible.

Credits

This article was originally published on Tomas "wereHamster" Carnecky back in Nov 2011
Included here mostly due to pure joy I received on stumbling onto this article again after so long.

\m/

Vinayak Mishra

Vinayak Mishra, a Cricket Enthusiast with keen interest in web and mobile applications. Hails from Mithila, Nepal, married to Rani and dad to his bundle of joy Bunu. Lives in New Delhi, India. You can follow him on Twitter or check out his website, vnykmshr.com.