how to stop middleware chain? - node.js

How can I properly end a middleware chain in case of error ?
In my code I have
if (someProblem) {
res.status(statuscode).json({message: 'oops'});
return;
}
Yet the midleware in the chain after that keeps getting called giving me the Can't set headers after they are senterror.

Middleware does not advance on its own. It only goes to the next step in the chain when you call next() so as long as you don't call next(), then the next step will not execute.
So, if you just send a response and return (without calling next()), then you should not have an issue.
The code you show in your question would not, all by itself, cause the error message you refer to so there must be more going on that you aren't showing us for that error to occur.

So you simply have to attach an errorHandler (which is a function that takes 4 parameters) before you create the actual server instance.
Anywhere in the app you can now simply create an error with var newError = new Error('my error message'); and pass it to the next callback with next(newError);
To stop the execution after the error has been thrown and to not send a response twice use return next (newError);
// example route
app.get('/test', function(req, res, next){
if (someProblem) {
var newError = new Error('oops');
return next(newError);
}
res.send('all OK - no errors');
});
// attach this errorHandler just before you create the server
app.use(function(error, req, res, next){
console.log(error);
res.status(500).json(error);
});
// this is where you create the server
var server = app.listen(4000, function(){
console.log('server started');
});

If you want your middleware to not go to the next step of the chain but to return the error you have to call next(error) callback.
This will call the error handler middleware where you can operate with the error and return it to the client if thats what you want.
To implement your custom error handler middleware you can use handleError(err, req, res, next)(error, req, res, next)

Related

Express js middleware not working when error is passed alongside ,req,res and next

So , I am trying to implement CSRUF in express and I want to have custom errors thrown instead of the default error handling of the middleware CSRUF example here.
The CSRF implemntetion is working correctly and when the token is invalid,an error is thrown in console and a response with a 403 status is send to browser.
I do not want the error to be handled by default.
When I create a custom error handler middleware as below,
function (err,req, res, next) {
console.log("reached")
if (err.code !== 'EBADCSRFTOKEN') return next(err)
console.log("Not working")
// handle CSRF token errors here
res.status(500)
res.send('form tampered with')
}
It appears that the middlware is not being implemented as the default error for CSRUF is being thrown.
Intrestingly,I noticed that when i have a custom middeware with an err parameter,the middleware appears to be ignored by the app.
Example(This works)
function (req, res, next) {
console.log("This is some middleware") //Console outputs
next()
}
However,When I add a err or error parameter to the function as below,it appears as though the middleware is not being used
function (req, res, next) {
console.log("This is some middleware.Err parameter has been passed") //Nothing is output to console
next()
}
I have read the Express error handling documentation and done as required but i still face the error,What could be the issue and how do i handle such.
I finally figured it out.
When I place the error handler middleware just after the CSRUF everything works i.e
app.post(route,middleware1,errorhandler,(req,res)={
//Any errors from middleware1 will now be catched by the errorhandler instead of the default error handler
//Some code here
})
The location of the errorhandler appears to play a big role

node express: should you always call next() in a get or post handler?

Until now I've defined my get and post handlers with just (req, res) as arguments, with the assumption being that I put these handlers last in the chain of middleware, and make sure that I handle any responses and error handling properly within these handlers... hence it doesn't matter that I don't make any reference to next.
Is this a valid and sensible approach, or is it good practice always to call next() even if (at present) there is nothing coming afterwards? For example, perhaps in the future you might want to do some handling after these routes... or maybe there's a reason I haven't yet come across why it's good practice to always call next().
For example, there is the following simple example in the express routing guide:
app.get('/example/b', function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res) {
res.send('Hello from B!')
})
Of course, I appreciate that this is a very simple example to illustrate that handlers can be chained, and is not intended to provide a complete framework for a get handler, but would it be better to define and use next even in the second handler, as follows?
app.get('/example/b', function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res, next) {
res.send('Hello from B!')
next()
})
Or is it actually common practice to assume that a handler function that sends a response back to the client should not call next()... i.e. the assumption should be that the chain will end at the handler that actually sends the response?
Or is there no established practice on this point?
I'm even wondering whether it might be common not to send any response in the get handler but to defer that to a dedicated response handler coming after... by which I mean an OK response handler rather than an error response handler (for which it seems to be common practice to defined a final error handler and call next(err)). So, in a non-error situation, you would call next() and in the following middleware you would do your res.status(200).send(req.mydata) where req.mydata is added in your get handler.
No. You should only call next() if you want something else to handle the request. Usually it's like saying that your route may match that request but you want to act like it didn't. For example you may have two handlers for the same route:
app.get('/test', (req, res, next) => {
if (something) {
return next();
}
// handle request one way (1)
});
app.get('/test', (req, res) => {
// handle request other way (2)
});
Always the first matching handler is called, so for the GET /test request the first handler will be called, but it can choose to pass the control to the second handler, as if the first didn't match the request.
Note that if the second handler doesn't intend to pass the request to the next handler, it doesn't even have next in its arguments.
If there was no second handler, then the standard 404 handler would be used if the first one called next().
If you pass an argument to next() then an error handling middleware will be called.
My rule of thumb is to handle the response in the handler if you're going to give a 20x (Success) response code, and in centralized error handling if not. That looks something like this in practice:
// ./routes/things.js
const express = require('express');
const Thing = require('../models/thing');
const Router = express.Router();
// note, the handlers might get pulled out into a controllers file, if they're getting more complex.
router.param('thingId', (req, res, next, id) => {
Thing.findById(id, (e, thing) => {
if (e) return next(e);
// let's say we have defined a NotFoundError that has 'statusCode' property which equals 404
if (!bot) return next(new NotFoundError(`Thing ${id} not found`));
req.thing = thing;
return next();
});
});
router.get('/', (req, res, next) => {
// possibly pull in some sort, limit, and filter stuff
Thing.find({}, (e, things) => {
if (e) return next(e);
res.send(things);
});
});
router.route('/:thingId')
.get((req, res) => {
// if you get here, you've already got a thing from the param fn
return res.send(req.thing);
})
.put((req, res, next) => {
const { name, description } = req.body; // pull whitelist of changes from body
let thing = req.thing;
thing = Object.assign(thing, { name, description }); // copy new stuff into the old thing
thing.save((e) => {
if (e) return next(e);
return res.send(thing); // return updated thing
});
});
Keeping each logical chunk in its own file can reduce repetition
// ./routes/index.js then mounts the subrouters to the main router
const thingsRoute = require('./things');
const express = require('express');
const router = express.Router();
/* .... other routes **/
router.use('/things', thingsRoute);
Error handling is then centralized, and can be mounted either in its own file or right on the app:
// in ./index.js (main app entry point)
const express = require('express');
// this will require by default ./routes/index.js
const routes = require('./routes');
const app = express();
const log = require('./log');// I prefer debug.js to console.log, and ./log.js is my default config file for it
/* ... other app setup stuff */
app.use(routes);
// you can mount several of these, passing next(e) if you don't handle the error and want the next error handler to do so.
app.use((err, req, res, next) => {
// you can tune log verbosity, this is just an example
if (err.statusCode === 404) {
return res.status(404).send(err.message);
}
log.error(err.message);
log.verbose(err.stack); // don't do stack traces unless log levels are set to verbose
return res.status(500).send(err.message);
});

Node.js Express - next() callbacks

In Node.js Express - using app.use functions-
why don't I have to do this:
app.use(function(req,res,next){
//do something here
next(req,res);
});
usually I just do this and it works
app.use(function(req,res,next){
//do something here
next();
});
?
next() already knows the req and res for the currently executing request, thus you just call it directly. It is a unique function created just for this request. It also keeps track of where you currently are in the middleware stack such that calling next() executes the next middleware in the chain.
If you look at the express source code for the router, you can actually see the locally defined next() function and can see how it has access to a bunch of closure-defined variables that include req, res and index counter that it uses for advancing through the middleware stack and a bunch of other variables. Thus, it already has access to everything it needs to launch the next middleware call so there is no reason to pass it those things.
FYI, one of the great things about using open source is that you can always just go look at the code yourself and see what it does.
When invoking next(), you have several choices:
You can invoke it as next() and this will just invoke the next middleware handler in the stack.
You can invoke it as next('route') and it will skip to the next route handler.
You can pass an error next(err) and stop all further middleware or router handling except for error handlers.
The details are documented here: http://expressjs.com/guide/error-handling.html.
Here's a note from that page:
next() and next(err) are analogous to Promise.resolve() and
Promise.reject(). They allow you to signal to Express that this
current handler is complete and in what state. next(err) will skip all
remaining handlers in the chain except for those that are set up to
handle errors as described in the next section.
The use of next accepts an optional Error object. if you pass nothing to it, it assumes you're ready to continue onto the next piece of middleware or your actual mounted handler. Otherwise, if you pass an instance of an Error object, you'll bypass your mounted handler (and sequential middleware) and go directly to the error handler.
app.use(function (req, res, next) {
if (!req.user || !req.user.isAuthorized) next(Error('not allowed'))
else next()
})
app.get('/:user', function (req, res, next) {
res.render('users/index', { user: req.user })
})
app.use(function (err, req, res, next) {
console.log(err.message) // not allowed
res.render('500', err)
})
I tried to understand the internal working by looking in the sources provided by jfriend00, but didn't wanted to loose too much time trying to isolate the specific part which handles the callbacks.
So I tried my own:
jsfiddle
function MW(req, res){
var req1 = req, res1 = res;
Array.prototype.shift.apply(arguments);
Array.prototype.shift.apply(arguments);
var MWs = arguments;
console.log(MWs, req1, res1);
function handle(index){
if(index ===MWs.length-1){
return ()=>{MWs[index](req1, res1, ()=>{})};
}
return ()=>{MWs[index](req1, res1, handle(index+1))};
}
var next = handle(0);
next();
}
Basically, it uses recursion to build the chain of callbacks.
You can then use it as Express use/get/post/put/...:
MW(req, res,
(req, res, next)=>{
console.log("first");
req.locals = {
token : 'ok'
};
res.canSend =false;
next();
},
(req, res, next)=>{
console.log("second");
console.log(req.locals.token, res.canSend);
next();
}
);

Express next function, what is it really for?

Have been trying to find a good description of what the next() method does. In the Express documentation it says that next('route') can be used to jump to that route and skip all routes in between, but sometimes next is called without arguments. Anybody knows of a good tutorial etc that describes the next function?
next() with no arguments says "just kidding, I don't actual want to handle this". It goes back in and tries to find the next route that would match.
This is useful, say if you want to have some kind of page manager with url slugs, as well as lots of other things, but here's an example.
app.get('/:pageslug', function(req, res, next){
var page = db.findPage(req.params.pageslug);
if (page) {
res.send(page.body);
} else {
next();
}
});
app.get('/other_routes', function() {
//...
});
That made up code should check a database for a page with a certain id slug. If it finds one render it! if it doesn't find one then ignore this route handler and check for other ones.
So next() with no arguments allows to pretend you didn't handle the route so that something else can pick it up instead.
Or a hit counter with app.all('*'). Which allows you to execute some shared setup code and then move on to other routes to do something more specific.
app.all('*', function(req, res, next){
myHitCounter.count += 1;
next();
});
app.get('/other_routes', function() {
//...
});
In most frameworks you get a request and you want to return a response. Because of the async nature of Node.js you run into problems with nested call backs if you are doing non trivial stuff. To keep this from happening Connect.js (prior to v4.0, Express.js was a layer on top of connect.js) has something that is called middleware which is a function with 2, 3 or 4 parameters.
function (<err>, req, res, next) {}
Your Express.js app is a stack of these functions.
The router is special, it's middleware that lets you execute one or more middleware for a certain url. So it's a stack inside a stack.
So what does next do? Simple, it tells your app to run the next middleware. But what happens when you pass something to next? Express will abort the current stack and will run all the middleware that has 4 parameters.
function (err, req, res, next) {}
This middleware is used to process any errors. I like to do the following:
next({ type: 'database', error: 'datacenter blew up' });
With this error I would probably tell the user something went wrong and log the real error.
function (err, req, res, next) {
if (err.type === 'database') {
res.send('Something went wrong user');
console.log(err.error);
}
};
If you picture your Express.js application as a stack you probably will be able to fix a lot of weirdness yourself. For example when you add your Cookie middleware after you router it makes sense that your routes wont have cookies.
Docs
How do I setup an error handler?
Error Handling
You define error-handling middleware in the same way as other middleware, except with four arguments instead of three; specifically with the signature (err, req, res, next):
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
IMHO, the accepted answer to this question is not really accurate. As others have stated, it's really about controlling when next handler in the chain is run. But I wanted to provide a little more code to make it more concrete. Say you have this simple express app:
var express = require('express');
var app = express();
app.get('/user/:id', function (req, res, next) {
console.log('before request handler');
next();
});
app.get('/user/:id', function (req, res, next) {
console.log('handling request');
res.sendStatus(200);
next();
});
app.get('/user/:id', function (req, res, next) {
console.log('after request handler');
next();
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
If you do
curl http://localhost:3000/user/123
you will see this printed to console:
before request handler
handling request
after request handler
Now if you comment out the call to next() in the middle handler like this:
app.get('/user/:id', function (req, res, next) {
console.log('handling request');
res.sendStatus(200);
//next();
});
You will see this on the console:
before request handler
handling request
Notice that the last handler (the one that prints after request handler) does not run. That's because you are no longer telling express to run the next handler.
So it doesn't really matter if your "main" handler (the one that returns 200) was successful or not, if you want the rest of the middlewares to run, you have to call next().
When would this come in handy? Let's say you want to log all requests that came in to some database regardless of whether or not the request succeeded.
app.get('/user/:id', function (req, res, next) {
try {
// ...
}
catch (ex) {
// ...
}
finally {
// go to the next handler regardless of what happened in this one
next();
}
});
app.get('/user/:id', function (req, res, next) {
logToDatabase(req);
next();
});
If you want the second handler to run, you have to call next() in the first handler.
Remember that node is async so it can't know when the first handler's callback has finished. You have to tell it by calling next().
next() without parameter invokes the next route handler OR next middleware in framework.
Summarizing rightly mentioned answers in one place,
next() : move control to next function in same route. case of
multiple functions in single route.
next('route') :move control to next route by skipping all remaining
function in current route.
next(err) : move control to error middleware
app.get('/testroute/:id', function (req, res, next) {
if (req.params.id === '0') next() // Take me to the next function in current route
else if (req.params.id === '1') next('route') //Take me to next routes/middleware by skipping all other functions in current router
else next(new Error('Take me directly to error handler middleware by skipping all other routers/middlewares'))
}, function (req, res, next) {
// render a regular page
console.log('Next function in current route')
res.status(200).send('Next function in current route');
})
// handler for the /testroute/:id path, which renders a special page
app.get('/testroute/:id', function (req, res, next) {
console.log('Next routes/middleware by skipping all other functions in current router')
res.status(200).send('Next routes/middleware by skipping all other functions in current router');
})
//error middleware
app.use(function (err, req, res, next) {
console.log('take me to next routes/middleware by skipping all other functions in current router')
res.status(err.status || 500).send(err.message);
});
Question also asked about use of next('route') which seems to be covered week in provided answers so far:
USAGE OF next():
In short: next middleware function.
Extract from this official Express JS documentation - 'writing-middleware' page:
"The middleware function myLogger simply prints a message, then passes on the request to the next middleware function in the stack by calling the next() function."
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
This page of Express JS documentation states "If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging."
USAGE OF next('route') :
In short: next route (vs. next middleware function in case of next() )
Extract from this Express JS documentation - 'using-middleware' page:
"To skip the rest of the middleware functions from a router middleware stack, call next('route') to pass control to the next route. NOTE: next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.
This example shows a middleware sub-stack that handles GET requests to the /user/:id path."
app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// render a regular page
res.render('regular')
})
// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
res.render('special')
})
Its simply means pass control to the next handler.
Cheers
Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next() function could be named anything, but by convention, it is always named “next”. To avoid confusion, always use this convention.
next() is the callback argument to the middleware function with req, and res being the http request and response arguments to next in the below code.
app.get('/', (req, res, next) => { next() });
So next() calls the passed in middleware function. If current middleware function does not end the request-response cycle, it should call next(), else the request will be left hanging and will timeout.
next() fn needs to be called within each middleware function when multiple middleware functions are passed to app.use or app.METHOD, else the next middleware function won’t be called (incase more than 1 middleware functions are passed). To skip calling the remaining middleware functions, call next(‘route’) within the middleware function after which no other middleware functions should be called. In the below code, fn1 will be called and fn2 will also be called, since next() is called within fn1. However, fn3 won’t be called, since next(‘route’) is called within fn2.
app.get('/fetch', function fn1(req, res, next) {
console.log("First middleware function called");
next();
},
function fn2(req, res, next) {
console.log("Second middleware function called");
next("route");
},
function fn3(req, res, next) {
console.log("Third middleware function will not be called");
next();
})

How to handle code exceptions in node.js?

I went through the documentation of Express, and the part describing error handling is completely opaque to me.
I figured the app they're referring to is an instance createServer(), right? But I have no clue how to stop node.js from blowing up the application process when an exception occurs during handling a request.
I don't need anything fancy really; I just want to return a status of 500, plus an otherwise empty response, whenever there's an exception. The node process must not terminate just because there was an uncaught exception somewhere.
Is there a simple example of how to achieve this?
var express = require('express');
var http = require('http');
var app = express.createServer();
app.get('/', function(req, res){
console.log("debug", "calling")
var options = {
host: 'www.google.com',
port: 80,
path: "/"
};
http.get(options, function(response) {
response.on("data", function(chunk) {
console.log("data: " + chunk);
chunk.call(); // no such method; throws here
});
}).on('error', function(e) {
console.log("error connecting" + e.message);
});
});
app.configure(function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.listen(3000);
crashes the entire app, producing traceback
mypath/tst.js:16
chunk.call(); // no such method; throws here
^ TypeError: Object ... has no method 'call'
at IncomingMessage.<anonymous> (/Library/WebServer/Documents/discovery/tst.js:16:18)
at IncomingMessage.emit (events.js:67:17)
at HTTPParser.onBody (http.js:115:23)
at Socket.ondata (http.js:1150:24)
at TCP.onread (net.js:374:27)
If you really want to catch all exceptions and provide some handling other than exiting the Node.js process, you need to handle Node's uncaughtException event.
If you think about it, this is a Node thing, and not an Express thing, because if you throw an exception from some arbitrary piece of code, there's no guarantee Express can or will ever see it, or be in a position to trap it. (Why? Exceptions don't interact very well with asynchronous event-driven callbacky code that is the Node style. Exceptions travel up the call stack to find a catch() block that's in scope at the time the exception is thrown. If myFunction defers some work to a callback function that runs when some event happens, then return to the event loop, then when that callback function is invoked, it's invoked directly from the main event loop, and myFunction is no longer on the call stack; if this callback function throws an exception, even if myFunction has a try/catch block, it's not going to catch the exception.)
What this means in practice is that if you throw an exception and don't catch it yourself and you do so in a function that was directly called by Express, Express can catch the exception and call the error handler you've installed, assuming you've configured some piece of error-handling middleware like app.use(express.errorHandler()). But if you throw the same exception in a function that was called in response to an asynchronous event, Express won't be able to catch it. (The only way it could catch it is by listening for the global Node uncaughtException event, which would be a bad idea first because that's global and you might need to use it for other things, and second because Express will have no idea what request was associated with the exception.)
Here's an example. I add this snippet of route-handling code to an existing Express app:
app.get('/fail/sync', function(req, res) {
throw new Error('whoops');
});
app.get('/fail/async', function(req, res) {
process.nextTick(function() {
throw new Error('whoops');
});
});
Now if I visit http://localhost:3000/fail/sync in my browser, the browser dumps a call stack (showing express.errorHandler in action). If I visit http://localhost:3000/fail/async in my browser, however, the browser gets angry (Chrome shows a "No data received: Error 324, net::ERR_EMPTY_RESPONSE: The server closed the connection without sending any data" message), because the Node process has exited, showing a backtrace on stdout in the terminal where I invoked it.
To be able to catch asynchronous errors I use domain. With Express you can try this code:
function domainWrapper() {
return function (req, res, next) {
var reqDomain = domain.create();
reqDomain.add(req);
reqDomain.add(res);
res.on('close', function () {
reqDomain.dispose();
});
reqDomain.on('error', function (err) {
next(err);
});
reqDomain.run(next)
}
}
app.use(domainWrapper());
//all your other app.use
app.use(express.errorHandler());
This code will make your asynchronous error be captured and sent to your error handler. In this example I use the express.errorHandler, but it works with any handler.
For more information about domain: http://nodejs.org/api/domain.html
You can use the default error handler that express uses, which is actually connect error handler.
var app = require('express').createServer();
app.get('/', function(req, res){
throw new Error('Error thrown here!');
});
app.configure(function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.listen(3000);
Update
For your code, you actually need to capture the error and pass it to express like this
var express = require('express');
var http = require('http');
var app = express.createServer();
app.get('/', function (req, res, next) {
console.log("debug", "calling");
var options = {
host:'www.google.com',
port:80,
path:"/"
};
http.get(options,
function (response) {
response.on("data", function (chunk) {
try {
console.log("data: " + chunk);
chunk.call(); // no such method; throws here
}
catch (err) {
return next(err);
}
});
}).on('error', function (e) {
console.log("error connecting" + e.message);
});
});
app.configure(function () {
app.use(express.errorHandler({ dumpExceptions:true, showStack:true }));
});
app.listen(3000);
express 5.0.0-alpha.7 came out 27 days ago. With this very specific pre-release version, you can now finally reject a promise inside a request handler and it will be handled properly:
Middleware and handlers can now return promises and if the promise is rejected, next(err) will be called with err being the value of the rejection. (source)
For example:
app.get('/', async () => {
throw new Error();
});
app.use((err, req, res, next) => {
res.status(500).send('unexpected error :(');
});
However, only use this as a fallback. Proper error handling should still happen inside catch-phrases inside the request handlers themselves with proper error status codes.
If you don't catch an uncaught exception in your application, it will crash catastrophically, meaning the server process will exit with non-zero error code, and users will never see any response. If you don't have a process manager like pm2 installed, it will also remain dead. To avoid this, and to catch every possible kind of error like logic errors or programmer errors, you need to place the code in a try-catch block. However, there is a really simple solution that avoids having to have a try-catch block around every single controller function. This article explains how.
Simply install express-async-errors and put this on top of your app.js:
const express = require('express');
require('express-async-errors');
...
Now every possible error in a controller is automatically passed to express error handler, no matter if it's async or sync, even if you write things like null.test. You can define an error handler like the following:
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
});
To make this more useful, you can even define your own error classes that inherits from Error, and throw it anywhere you want in your controllers, and it will be automatically caught by Express. Then check if (err instanceof MyCustomErrorClass) in your error handler to display custom messages in your 500 page.

Resources