Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

exit from chain of route specific middleware in express/ nodejs

I have a chain of "route specific middleware" for this route, like so:

    var express = require('express');
    var server = express();
    var mw1 = function(req, resp, next) {
        //do stuff
        if (success) {
            next();
        } else {
            req.connection.destroy(); //without calling next()
        }
    };
    var mw2 = function(req, resp, next) {
        //do stuff
        if (success) {
            next();
        } else {
            req.connection.destroy(); //without calling next()
        }
    };
    server.post('/some/path', [mw1, mw2], function(req, resp) {
        //write response
    });

[mw1, mw2] are the middleware specific to the route /some/path.

This is different from server-wide middleware like this:

    server.use(mw1);
    server.use(mw2);

Where it applies to all routes defined.

Now my issue is that I want to exit from the chain. I.e. if success is false in mw1, I do not wish for mw2 to be called. If success is false in mw2, I do not without for the route function to be called. Presently, both mw1 and mw2 appear to be getting called whether or not next() is called - and I do not know why.

How can I go about doing this?

like image 590
bguiz Avatar asked Jun 21 '13 09:06

bguiz


1 Answers

A little more tinkering yielded the answer:

var express = require('express');
var server = express();
var mw1 = function(req, resp, next) {
  //do stuff
  if (success) {
    next();
  } else {
    resp.send(406, 'Invalid because of this');
    req.connection.destroy(); //without calling next()
  }
};
var mw2 = function(req, resp, next) {
  //do stuff
  if (success) {
    next();
  } else {
    resp.send(406, 'Invalid because of that');
    req.connection.destroy(); //without calling next()
  }
};
server.post('/some/path', [mw1, mw2], function(req, resp) {
  //write response
});

The trick was send a response: resp.send(406, 'Invalid because of this');

Just prior to destroying the connection: req.connection.destroy();

In fact not destroying the connection, I found to also work, in the general case.

(But was required in my specific case, and is out of the scope of this question.)

If the response has already been sent, then express does not automatically call next() for you, as it appeared to do otherwise.

like image 166
bguiz Avatar answered Sep 22 '22 21:09

bguiz