Exiting the route-specific middleware chain in express / nodejs

I have a “route specific middleware” chain for this route, for example:

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 middleware specific to the /some/path route.

This differs from server middleware in the following ways:

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

Where it applies to all indicated routes.

Now my problem is that I want to get out of the chain. That is, if success false in mw1 , I do not want mw2 to mw2 called. If success is false in mw2 , I do not need to call the route function. Currently, both mw1 and mw2 seem to be getting a call whether next() is called or not - and I don't know why.

How can i do this?

+8
javascript middleware express connect
source share
3 answers

A little more messing around gave 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 sent a response: resp.send(406, 'Invalid because of this');

Before destroying a connection: req.connection.destroy();

In fact, without destroying the connection, I found that it also works in the general case.

(But this was necessary in my particular case and is beyond the scope of this question.)

If a response has already been sent, then the expression will not automatically call next() for you, as it seems otherwise.

+1
source share

You can call next( 'route' ) , as stated in the express api link, application routing section :

You can specify multiple callbacks, they are all treated the same and behave like middleware, with one exception that these callbacks can invoke next('route') to bypass the remaining callbacks.

Example

 var express = require('express') , app = express() ; // keep an eye on the function names app.post( '/some/path', middleware1, middleware2, function route1( req, res, next ) { // write response }); app.all( '*', function route2( req, res, next ) { // do something like handle a 404 request }); app.use(function errorHandler( err, req, res, next ) { // handle error }); function middleware1( req, res, next ) { // ... if ( !success ) { // bypasses middleware2 and route1, route2 will be called return next( 'route' ); } // calls middleware2 next(); } // intentionally similar to middleware1 to keep things clear function middleware2( req, res, next ) { if ( !success ) { // bypasses route1 and route2 // errorHandler will be called with the error return next( Error( 'middleware 2 failed' ) ); } // calls route1 next(); } 
+17
source share

I got the impression that if you do not call next() and do not send a response in the route processing function, the expression just hangs. Also, FWIW I did not use an array, mine looks like server.post('/some/path', mw1, mw2, function(req, resp) {...

Anyway. Restructuring your code may be one option, so you only have one processing function. Do you have a good reason mw1 and mw2 are middleware instead of the usual asynchronous functions called by your handlers?

 var express = require('express'); var server = express(); var mw1 = function(req, res, callback) { // do stuff with req/res if necessary but don't send a response if (success) { callback(null); } else { callback('Error'); } }; var mw2 = function(req, res, callback) { //do other stuff but don't send a response if (success) { callback(null); } else { callback('Error'); } }; function mwBoth(req, res){ mw1(req, res, function(err){ if(err){ return res.send(500) }; mw2(req, res, function(err){ if(err){ return res.send(500) }; // neither had an error res.redirect('/some/other/path'); }); }); }; server.post('/some/path', mwBoth); 
+1
source share

All Articles