A common pattern in my Express app is to include the following in all my routes:
//...code which could result in an err
if (!err) return res.send(200);
console.log(err); // Would prefer to omit this line
res.send(500);
Right now, I need to write console.log(err) in all my routes. I'd prefer to just automatically log the err variable every time a 500 is sent. Is there any way to hook into Express and automatically log the call stack and/or err for all 500 responses?
From your explanation, you seem to be including error handling in all your routes.
You probably should create a global interceptor error handler which can perform the logging for you and still be the base error handler if you have a 500 error type.
//if your express var is app
var errorHandler = function(err, req, res, next){
console.log(err.stack);
res.send(500);
// or you could call res.render('error'); if you have a view for that.
};
app.use(app.router); // this has to come before your interceptors
app.use(notFound); // your page not found interceptor
app.use(errorHandler);
Related
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
app.get('/test', (req, res, next) => {
const err = new Error('Test');
next(err);
});
express will log the error and stacktrace to the console. Is there a way that I can suppress the logging?
If you put an error handler middleware in your Express implementation to handle the next(err) call like this:
// defined as the last route
app.use(function (err, req, res, next) {
res.status(500).send('Something broke!')
});
then, Express won't log any error and you can control what response is sent for the error.
I'd suggest reading this page on Express error handling: https://expressjs.com/en/guide/error-handling.html.
If you look in the express code where this logging comes from, it comes from this code:
function logerror(err) {
/* istanbul ignore next */
if (this.get('env') !== 'test') console.error(err.stack || err.toString());
}
which curiously enough shows that if you do this:
app.set('env', 'test');
or you set NODE_ENV=test in the environment before launching your server, then it will skip the error logging too. But, it's much better to just control things with your own error handler as I show about where you can also control what type of response is sent.
I am working a REST web application backend and I got some problem when linking my middleware together.
For example, the stack of the middlewares that each request has to go through is like [before1, service, after1], and here's the code for the middleware "before1", this is just the code I used for testing:
'use strict';
var express = require('express');
var router = express.Router();
router.use(function(request, response, next){
console.log('This is middleware BEFORE1');
var success = true
if (!success){
// Go the logging middleware underneath
next();
}
else{
// Go to the 'service' middleware
next('route');
}
})
router.use(function(request, response, next){
console.log('This is middleware LOGGING');
response.sendStatus(400);
response.end();
})
module.exports = router;
The above code is simply saying if the 'before1' succeeds, it should go straight to call 'service' middleware, and otherwise go to the logging middleware underneath and end the request. But my problem is that I can't figure out a way that it could skip the logging middleware, I searched and found next('route') could help, but it didn't work here. What have I missed?
Thanks in advance!
EDIT:
Or more preferably, it's the best if I can issue an error in any of my middleware and handle all types of errors properly using a error handler middleware.
The skeleton of my top level code is the following:
// An array of middleware to be executed asynchronously
operations = [before1, service, before2];
async.series(operations, function(err) {
if(err) {
// one of the functions passed back an error so handle it here
console.log('Handling error!!!!');
res.end();
// return next(err);
}
console.log('middleware get executed');
// no errors so pass control back to express
next();
});
But I am not sure How should change my middlewares accordingly in order to do that.
next is a node-style callback, which means fn(err, ..), so your next('route') will only work to invoke errorhandlers.
You can implement your series directly by supplying an array of functions to the route, and using an express error handler as the catch all (see http://expressjs.com/guide/error-handling.html)
I just recently started working on an express.js based application, which also uses the pg module (https://github.com/brianc/node-postgres)
I also spent a significant amount of time, reading about node and express approach error handling, the benefits of properly designing middleware, etc. Yet, a recurring problem is still buzzing me without a solution.
Say, I have the following router method:
app.get("/:someThing/:someId", function(req, res, next) {
pgClient.query("some SQL query", function(err, data) {
if (err) { return next(err); } // some 500 handler will take it
if (data.rows.length == 0) {
next(); // send it over to a 404 handler
}
//finally, here we get the chance to do something with the data.
//and send it over via res.json or something else
});
});
If I've read correctly, this should be the proper way to do it. Yet, I bet you can also admt that it is too much of boilerplate to rewrite over and over ... and over again, even in the very same router method, in case we have multiple nested callbacks.
I've been asking myself what the best way to handle such a situation centrally would be. All of my ideas involve intercepting the pgClient.query method. In one, the query method will simply throw the error instead of passing it to the callback. In another, the call to the pgClient.query will send the router method's next to pgClient. Then the intercepted query method will know how to deal with the next being passed to it.
From what I know, throwing errors around is not really the appropriate way to get it to the 500 handlers. On another hand, passin next as an option to pgClient, gives such a low level a lot of knowledge about the the layers above, which based on my knowledge and experience, can lead to coupling, and is not very good either.
What do you suggest?
You can use connect-domain middleware. It works with connect and express and based on Doman API.
You need to add connect-domain middleware as first middleware in stack. Thats all. Now you can throw errors everywhere in your async code and they will be handled with domain middleware and passed to express error handler.
Simple example:
// Some async function that can throw error
var asyncFunction = function(callback) {
process.nextTick(function() {
if (Math.random() > 0.5) {
throw new Error('Some error');
}
callback();
});
};
var express = require('express');
var connectDomain = require('connect-domain');
var app = express();
app.use(connectDomain());
// We need to add router middleware before custom error handler
app.use(app.router);
// Common error handler (all errors will be passed here)
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.listen(3131);
// Simple route
app.get('/', function(req, res, next) {
asyncFunction(function() {
res.send(200, 'OK');
});
});
I'm developing an express app.
I currently have the following in my server.js
process.on('uncaughtException', function (err) {
console.log( "UNCAUGHT EXCEPTION " );
console.log( "[Inside 'uncaughtException' event] " + err.stack || err.message );
});
Which stops the server crashing every time there's an error, however, it just sits there...
is it possible to instead of console.log, to send a 500 error page with the error details?
I don't think you can from within the uncaughtException do a response since that could happen even when there is no request occurring.
Express itself provides a way to handle errors within routes, like so:
app.error(function(err, req, res, next){
//check error information and respond accordingly
});
Per ExpressJS Error Handling, add app.use(function(err, req, res, next){ // your logic }); below your other app.use statements.
Example:
app.use(function(err, req, res, next){
console.log(err.stack);
// additional logic, like emailing OPS staff w/ stack trace
});