I'm building an API (using Expressjs v4) and typically I've dealt with errors within the route rather than using middleware. For example:
router.use('/', function(req, res, next) {
...
if (err)
return res.status(500).send({type: "serverError", message: "Something has gone wrong on our end."});
}
I now realise that middleware is the "way to go." I've seen the rather limited documentation on the Expressjs site here: http://expressjs.com/guide/error-handling.html but still unsure of a few things.
I've added in the server.js
:
function errorHandler(err, req, res, next) {
}
but how do I supposed to handle the different types of errors (400,404,500 etc)?
I'm finding myself writing 3 lines of code each time an error occurs:
//A route
var err = new Error();
err.status = 404;
return next(err);
and I can access the status using:
function errorHandler(err, req, res, next) {
console.log(err.status);
if(err.status == "400")
//do something
else
//etc etc
}
Surely there's an easier way than this? Am I missing something?
You should create your own Error type that allows you to provide all the information necessary to act on the error.
var util = require('util');
function HttpError(message, statusCode){
this.message = message;
this.statusCode = statusCode;
this.stack = (new Error()).stack;
}
util.inherits(Error, HttpError);
module.exports = HttpError;
Then include your new error object in your code and use it like
next(new HttpError('Not Found', 404));
Or you could go crazy and implement an error type for each response code pre-populating the statusCode
part.
Ref: What's a good way to extend Error in JavaScript?
Instead manually creating error, you can delegate that error like below.
return next(err);
And your error will go deep down all the routes defined until it find routes with below signature.
app.use(function (err, req, res, next) {
});
You can see the err argument in above route.
Ideally you can use below two methods for both DEVELOPMENT & PRODUCTION environment.
if (process.env.NODE_ENV === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
logger.log('info', err.message + " expected URL was " + req.url);
res.status(err.status).send(err.status, {
message: err.message,
error : err
});
});
}
app.use(function (err, req, res, next) {
res.status(err.status || 500);
logger.log('error', err.message + " expected URL was " + req.url);
res.status(err.status).send(err.status, {
message: err.message,
error : {}
});
});
You can capture actual populated error object in there.