node.js - handling - El controlador de errores de middleware Express 4 no se llama
node js error handling (1)
El problema es que los controladores de errores siempre deben estar al final de la pila de aplicaciones. Esto significa que puede mover el controlador de errores de su middleware a su app.js y usarlos después de sus necesidades (app.use () ) o incluir sus rutas antes de su middleware.
Para ciertas páginas tengo manejo personalizado de errores 500, 404 y 403 en mi aplicación. Así, por ejemplo, después de una consulta de base de datos fallida, iría:
return next({status: 404, message: ''Record not found''});
o
return next(new Error(''Bad things have happened'')});
En mi middleware tengo un manejador de errores:
app.use(function (err, req, res, next) {
// handle error
});
El problema es que el controlador de errores nunca se llama, en su lugar, la pila de llamadas de error se imprime en el navegador. Quiero que el controlador rinda una página de error personalizada.
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()));
});
rutas.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
});
};