Express 4 middleware error handler not being called

匿名 (未验证) 提交于 2019-12-03 00:46:02

问题:

For certain pages I have custom 500, 404 and 403 error handling in my app. So for instance after an unsuccessful database query I'd go:

return next({status: 404, message: 'Record not found'});

or

return next(new Error('Bad things have happened')});

In my middleware I have an error handler:

app.use(function (err, req, res, next) {     // handle error });

Problem is that the error handler is never called, instead the error callstack is being printed into the browser. I want the handler to render a custom error page.

app.js

var express = require('express')     , app = express()     , swig = require('swig')     , config = require('./lib/config')     , env = process.env.NODE_ENV || 'development'     , path = require('path');  config.configure(env);  app.engine('html', swig.renderFile); app.set('view cache', false);  swig.setDefaults({     cache: config.get('swigCache') });  app.set('view engine', 'html'); app.set('views', __dirname + '/lib/views');  require('./lib/util/swig'); require('./lib/initialisers/mongodb')(); require('./lib/initialisers/aws')(); require('./lib/middleware')(app); // first load middleware require('./lib/routes')(app); // then routes  var server = app.listen(config.get('port'), function() {     console.info('config: ' + JSON.stringify(config.getCurrent()));     console.info('NODE_ENV: ' + env);     console.info('server running: ' + JSON.stringify(server.address())); });

routes.js

module.exports = function(app){      app.get('/', require('./views/').index);     app.get('/blog', require('./views/blog').index);     app.get('/blog/:slug', require('./views/blog').getBySlug);      app.route('/report/:slug')         .get(require('./views/report/').index)         .post(require('./views/report/').doReport);          // Very long file with tons of routes. Simplified version.

middleware.js

var express = require('express')     , app = express()     , path = require('path')     , logger = require('morgan')     , cookieParser = require('cookie-parser')     , bodyParser = require('body-parser')     , passport = require('passport')     , session = require('express-session')     , mongoStore = require('connect-mongo')(session)     , compression = require('compression')     , favicon = require('serve-favicon')     , config = require('./config')     , flash = require('connect-flash')     , multer = require('multer')     , csrf = require('csurf');  module.exports = function(app) {      app.use(bodyParser.urlencoded({ extended: false }))     app.use(bodyParser.json());     app.use(cookieParser());     app.use(csrf({ cookie: true }));     app.use(express.static(path.join(__dirname, config.get('staticContentPath')), {         maxAge: (60 * 60 * 24) * 1000     }));      app.use(session({         resave: true,         saveUninitialized: true,         secret: 'da755fc0-6882-11e4-9803-0800200c9a66',          cookie: {             maxAge: 24 * 60 * 60 * 1000 // 24 hrs         },          store: new mongoStore({             url: config.getMongoConn()         })     }));      app.use(logger('dev'));     app.use(flash());      /**      * 301 redirects      */     app.use(function(req, res, next) {          var host = req.get('host');          // AWS IP --> http         if (host == 'xx.xxx.xxx.xxx') {             return res.redirect(301, config.get('url') + req.originalUrl);         }          // AWS origin --> http         if(host == 'xxx-xxx-xxx-xxx-xxx.ap-southeast-2.compute.amazonaws.com'){             return res.redirect(301, config.get('url') + req.originalUrl);         }          // www --> http         if (/^www\./.test(host)) {             host = host.substring(4, host.length);             return res.redirect(301, req.protocol + '://' + host + req.originalUrl);         }          // Trailing slash --> http         if (req.path.substr(-1) == '/' && req.path.length > 1) {             var query = req.url.slice(req.path.length);             return res.redirect(301, req.path.slice(0, -1) + query);         }          next();     });      // Delete expired Mongo sessions from DB     app.use(function (req, res, next) {         req.session._garbage = new Date();         req.session.touch();         next();     });      /**      * Setting Cache control header for Ajax requests to 30 minutes      */     app.use(function (req, res, next) {          if(req.xhr){             res.header('Cache-Control', 'max-age=' + 1800 + ', public');         }          next();     });      app.use(compression());      app.use(         multer({             dest: config.get('uploads').folders.temp         })     );      app.use(passport.initialize());     app.use(passport.session());     var initPassport = require('./passport/init');     initPassport(passport);      app.use(function (req, res, next) {          res.locals = {             root : 'http://' + req.headers.host,             sitename : require('./config').get('sitename'),             config: config.get('env'),             url : config.get('url'),             user : req.user,             flash : req.flash()         };          next();     });      app.use(function (err, req, res, next) {          if (err.code !== 'EBADCSRFTOKEN'){             return next(err);         }          if(req.xhr){             return res.ok({payload: null}, '403 invalid csrf token');         }          // TODO handle CSRF token errors here         res.status(403);         res.send('form tampered with')     });      // This is never called when throwing errors like     // next(new Error('some error') or     // next({status: 500, message:'server error'});     app.use(function (err, req, res, next) {         console.error(err.stack);         // render an error page     }); };

回答1:

The problem is, that your error handlers should always be at the end of your application stack. This means, that you can either move the error handler from your middleware to your app.js and use them after your requires (app.use()) or include your routes before your middleware.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!