Read my book

I wrote books about Webpack and React. Check them out!

Sunday, March 17, 2013

Middleware Pattern in JavaScript

Tower Complete by teotwawki
If you have ever used Express or some other web framework you are likely familiar with the concept of middleware. It is something that allows us to shape given input before moving into actual logic. Sometimes it may be beneficial to set up a post middleware as this allows you to define triggers based on what has happened. You can see this sort of solution at Mongoose for instance.

A while ago I figured that implementing a middleware scheme would clean up the API of a library of mine, rest-sugar. It is a library that greatly simplifies the creation of RESTful APIs. And I have been polishing it and related technologies lately. Express-style middleware API seemed like a good fit so I implemented that. There are both pre and post filters in place now and I find the interface quite nice.

The following snippet illustrates how the pattern works. Note that it is possible to simplify it further in case you need only one type of filters. In that case you do not need to keep track of context like here.
function init() {
    var handlers = {
        pre: [],
        post: []
    };
    var context;

    // ... your logic goes here

    return {
        use: function(fn) {
            handlers[context].push(fn);
        },
        pre: function(fn) {
            context = 'pre';
            fn();
        },
        post: function(fn) {
            context = 'post';
            fn();
        }
    };
}

// evaluate the middleware at your logic
// Using https://github.com/caolan/async here.
function evaluateHandlers(handlers, req, res, done, data) {
    async.series(handlers.map(function(fn) {
        return function(cb) {
            fn(req, res, cb, data);
        };
    }), done);
}

// sample middleware
function only(method) {
    return function(req, res, next) {
        if(req.method == method) return next();

        unauthorized(res);
    };
}
exports.only = only;

// and usage
var app = express();

...

var api = init(app);

api.pre(function() {
    api.use(only('GET'));
})

api.post(function() {
    api.use(function(req, res, next, data) {
        // trigger now

        // and remember to call next to avoid getting stuck!
        next();
    });
});
Even though the idea is quite simple I like how it gives me a nice way to define extension points to my APIs. You can also define factories to construct middlewares you need. In this case only is such a factory. That is another quite powerful and handy pattern enabled by closures.