Exit after res.send() in Express.js

node.jsExpress

node.js Problem Overview


I have a fairly simple Express.js app with a login component that I'd like to exit early if login fails. I'm seeing indications that the app isn't doing that and I haven't found a definitive answer that indicates whether calling res.send() halts any further processing. Here's my code as it stands now:

client.login( username, password, function( auth, client ) {
  if( !auth ) {
    res.send( 401 );
  }

  // DO OTHER STUFF IF AUTH IS SUCCESSFUL
}

If I read the source code correctly, it should end the request (aborting further processing), but I'm new to node, so I'm not quite ready to trust what I think I'm reading. To boil it down, I guess I'm mostly looking for a definitive answer from a more trustworthy source that my own interpretation of unfamiliar source code. If send() doesn't abort processing, what's the right way to do that?

node.js Solutions


Solution 1 - node.js

Of course express can not magically make your javascript function stop executing from somewhere else.

I don't like the next([error]) solution because I think errors should be only used for circumstances you usually don't expect (like an unreachable database or something). In this case, a simple wrong password would cause an error. It is a common convention to not use exceptions/errors for ordinary control flow.

I therefore recommend to place a return statement after the res.send call to make your function stop executing further.

client.login( username, password, function( auth, client ) {
  if( !auth ) {
    res.send( 401 );
    return;
  }

  // DO OTHER STUFF REALLY ONLY IF AUTH IS SUCCESSFUL
}

Solution 2 - node.js

If you are using express as your framework, you should call next() instead.

Each handler in express receives 3 parameters (unlinke 2 for basic http) which are req, res and next

next is a function that when called with no arguments will trigger the next handler in the middleware chain.

If next is called with an arguments, this argument will be interpreter as an error, regardless of the type of that argument.

Its signature is next([error]). When next is called with an error, then instead of calling the next handler in the middleware chain, it calls the error handler. You should handle the 401 response code in that error handler. See this for more info on error handling in Express

EDIT: As @Baptiste Costa commented, simply calling next() will not cease the current execution but it will call on the next middleware. It is good practice to use return next() instead to prevent Node from throwing errors further on (such as the can't set headers after they are sent - error). This includes the above suggestion of error throwing which is common:

return next(new Error([error]));

Solution 3 - node.js

For your specific case you can just add the 'else' statement:

client.login( username, password, function( auth, client ) {
    if( !auth ) {
        res.send( 401 );
    }else {
       // DO OTHER STUFF IF AUTH IS SUCCESSFUL
    }
}

Or, in general, you can use 'return':

return res.send( 401 );

Solution 4 - node.js

in these cases , i tend to use a try...catch bloc .

client.login( username, password, function( auth, client ) { 

 try{
   if(error1){
    throw {status : 401 , message : 'error1'}
   }
   if(error2){
    throw {status : 500 , message : 'error2'}
   }
 }catch(error){
   res.status(error.status).json(error.message);
 }

}

Solution 5 - node.js

Simply do something like this to stop further execution.

function (request, response, next) {
    var path = request.body.path;
  
    if(path === undefined){
        response.status(HttpStatus.BAD_REQUEST);
        response.send('path is required!');
    }

    next(response)
};

Solution 6 - node.js

You only need to do a return to end the flow:

return  res.send( 401 );

That will send the 401 response back and won't proceed forward in the flow.

Solution 7 - node.js

Why is no-one suggesting using an 'else' block?

if(!auth){
    // Auth fail code
    res.send 'Fail'
} else {
    // Auth pass code
    res.send 'Pass'
}

'next' is used when creating your own middleware for the "app.use(function(req, res, next));". If you have set up a route like "app.get(route, function(req, res));" then the code in the function is where you can have the code you are specifying without needing to use 'next'.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRob WilkersonView Question on Stackoverflow
Solution 1 - node.jsSteve BeerView Answer on Stackoverflow
Solution 2 - node.jsFlobyView Answer on Stackoverflow
Solution 3 - node.jsRoccoDen91View Answer on Stackoverflow
Solution 4 - node.jsnoumane agouzilView Answer on Stackoverflow
Solution 5 - node.jsVarunView Answer on Stackoverflow
Solution 6 - node.jsalexalejandroemView Answer on Stackoverflow
Solution 7 - node.jsfrankView Answer on Stackoverflow