11

There are a few posts on this question but none that answers the issue directly, head-on. Let me clarify that I understand (or so I think) the use of next(), next('route'), return next(), return and their impact on control flow. My entire middleware for the app consists of a series of app.use, as in:

 app.use(f1);
 app.use(f2);
 app.use(f3);
 app.use(f4);
 ...

In each of these middlewares, I have possibility of sending the response and be done without any need for further processing. My problem is that I am unable to stop the processing from going to the next middleware.

I have a clumsy work around. I just set a res.locals.completed flag after sending a response. In all the middlewares, at the very start, I check this flag and skip processing in the middleware if the flag is set. In the very first middleware, this flag is unset.

Surely, there must be a better solution, what is it? I would think that Express implicitly would do this checking and skip the middlewares through some express-specific method?

Sunny
  • 9,245
  • 10
  • 49
  • 79
  • 1
    Can you show what's in f1, f2, etc.? If you use `res.send(...)` *and* do not call `next()`, you should terminate the request-response cycle while not going into the next middleware. – maxdec Nov 11 '15 at 11:21

1 Answers1

14

According to the express documentation on http://expressjs.com/guide/using-middleware.html

If the current middleware does not end the request-response cycle,
it must call next() to pass control to the next middleware,
otherwise the request will be left hanging.

so if a middleware needs to end the request-response early, simply do not call next() but make sure that the middleware really ends the request-response by calling res.end, res.send, res.render or any method that implicitely calls res.end

app.use(function (req, res, next) {
  if (/* stop here */) {
    res.end();
  } else {
    next();
  }
});

Here is an example server showing that it works

var express = require('express');
var app = express();

var count = 0;
app.use(function(req, res, next) { 
  console.log('f1'); 
  next();
 })
app.use(function(req, res, next) {
  console.log('f2');
  if (count > 1) {
    res.send('Bye');
  } else {
    next();
  }
})
app.use(function(req, res, next) {
  console.log('f3');
  count++;
  next();
})

app.get('/', function (req, res) {
  res.send('Hello World: ' + count);
});

var server = app.listen(3000);

you will see the after 3 requests, the server shows "Bye" and f3 is not reached

Jerome WAGNER
  • 21,986
  • 8
  • 62
  • 77
  • Your response is logical. Upvoted. However, res.end or res.send continue to process other middleware functions included in the app.use list. The use of next('route') also does not stop this. Of course, plain Javascript or programming thinking would also suggest that that would/should happen. What I am asking for, is for other middleware functions to know that they should not be executed because someone has already done their work. "next" just takes control over to the next function listed in app.use, and continues execution even though if it is called after end() or send(). – Sunny Nov 11 '15 at 11:42
  • 1
    I am not sure I understand. calling next() means that you want the next middleware to be called. You want the next middleware to be called but not executed ?? – Jerome WAGNER Nov 11 '15 at 13:16
  • If a response is sent in middleware f1, I do not want other middlewares to be called for this request. I am referring to other middlewares in the app.use list. Now, I am setting a flag (in req or res object) on sending a response and when the other middlewares are called (because I cannot figure out how to stop that from happening after a send()), they first check the flag and if the flag is set, they simply call return thereby skipping execution and moving to the next middleware... It works but I want a better way... – Sunny Nov 11 '15 at 16:03
  • 1
    see my example server in the answer. Not calling next() and calling res.send() correctly stops the middleware flow – Jerome WAGNER Nov 11 '15 at 17:29
  • Your code confirms what I thought should happen. I think there must be some other error in my code. I will check that. Accepting your answer. Helped clarify my doubts. Thanks. I think that your answer will be of help to others too, for sure. – Sunny Nov 11 '15 at 17:44
  • Can you take a look at this question?http://stackoverflow.com/questions/33748618/sendfile-issues-with-respect-to-control-flow-in-express-middleware – Sunny Nov 17 '15 at 03:25
  • Something like these examples should be edited into the Express documentation. At the very least, the documentation should define what constitutes "end[ing] the request-response cycle" as you have clearly done here. – shoover Jul 10 '17 at 23:49