5

If I've made some middleware that works together, what's the best convention for grouping and managing the functionality?

In my server.js file, I've currently just got them listed one after another with app.use calls.

It's occurred to me however that if the first one in my set doesn't produce any data, the subsequent ones in the group are fine to skip. I guess this is ultimately an aggregation although I haven't seen any examples of such in other projects.

Alexander Trauzzi
  • 7,277
  • 13
  • 68
  • 112

2 Answers2

1

The connect middleware has a good example for this kind of problem. Take a look at the bodyParser:

app.use(connect.bodyParser());  // use your own grouping here

is equivalent to

app.use(connect.json());
app.use(connect.urlencoded());
app.use(connect.multipart());

Internally the bodyParser function just passes the req and res objects through each of the before mentioned middleware functions

exports = module.exports = function bodyParser(options){
  var _urlencoded = urlencoded(options)
    , _multipart = multipart(options)
    , _json = json(options);

  return function bodyParser(req, res, next) {
    _json(req, res, function(err){
      if (err) return next(err);
      _urlencoded(req, res, function(err){
        if (err) return next(err);
        _multipart(req, res, next);
      });
    });
  }  
};

The full code can be found at the github repo

zemirco
  • 16,171
  • 8
  • 62
  • 96
0

edit

Informed in the comments bellow that passing an array will acieve the exact same thing, so no need for an additional module. :-)


I was looking for a way to do this too as my application is very granular, but I didn't want to nest everything as in the other answer.

I'm sure there is something more comprehensive out there already, but I did this in the end:

 /**
 * Macro method to group together middleware.
 */
function macro (...middlewares) {
    // list of middlewares is passed in and a new one is returned
    return (req, res, next) => {
        // express objects are locked in this scope and then
        // _innerMacro calls itself with access to them
        let index = 0;
        (function _innerMacro() {
            // methods are called in order and passes itself in as next
            if(index < middlewares.length){
                middlewares[index++](req, res, _innerMacro)
            } else {

                // finally, next is called
                next();
            }
        })();
    }
}

And then use it like this:

var macro = macro(
    middleware1,
    middleware2,
    middleware3
);

app.post('/rout', macro);
James Trickey
  • 1,322
  • 13
  • 21
  • Or just `app.post('/rout', middleware1, middleware2, middleware3)`, or `let mw = [ middleware1, middleware2, middleware3 ]; app.post('/rout', mw)` (for easier reuse) – robertklep Sep 27 '17 at 12:27
  • The fist example is exactly what i was trying to avoid as i ended up with a lot of duplication that way, but i didnt know you could use arrays. Very nice, thank you. – James Trickey Sep 27 '17 at 12:49
  • Now i know why there was nothing out there to do it, was inbuilt the whole time! :-) – James Trickey Sep 27 '17 at 12:50
  • The original question is pretty old, so perhaps at the time it wasn't yet possible to pass arrays-of-middleware :D – robertklep Sep 27 '17 at 12:51