Express 4中间件错误处理程序未被调用 [英] Express 4 middleware error handler not being called

查看:137
本文介绍了Express 4中间件错误处理程序未被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于某些页面,我的应用程序中自定义了500、404和403错误处理.因此,例如,在数据库查询失败后,我会去:

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'});

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

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

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
    });
};

推荐答案

问题是,错误处理程序应始终位于应用程序堆栈的末尾.这意味着,您可以将错误处理程序从中间件移至app.js,并在需要后使用它们( app.use()),也可以在中间件之前添加路由.

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.

这篇关于Express 4中间件错误处理程序未被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆