express.js 4: 在路由器的 errorHandler 中捕获 bodyParser 错误

express.js 4: catch bodyParser error in router's errorHandler

如何在 express.js 4 中捕获路由器错误处理程序中的 bodyParser 错误?

示例代码:

var express = require('express');
var bodyParser = require('body-parser');

var app = express();

// use bodyParser.json()
app.use(bodyParser.json());

// setup route /test
var testRouter = express.Router();
testRouter.post('/', function(req, res, next) {
  next(new Error('not implemented'));
});
testRouter.use('/', function(err, req, res, next) {
  res.send('testRouter error: ' + err.message);
});
app.use('/test', testRouter);

// default error handler
app.use(function(err, req, res, next) {
  res.send('default error handler: ' + err.message);
});

module.exports = app;

/test 发送空主体的 POST 请求将 return testRouter error: not implemented。此消息来自 testRouter 中定义的错误处理程序,这是我期望发生的情况。

但是,向 /test 发送一个 POST 请求并带有格式错误的 json 正文将 return default error handler: [bodyParser error]。此消息来自默认错误处理程序。

我希望 testRouter 中的错误处理程序能够处理对 /test 的请求中发生的所有 bodyParser 错误。我怎样才能做到这一点?

您需要 testRouter 使用主体解析器中间件:

// not this:
app.use(bodyParser.json());

// but this:
testRouter.use(bodyParser.json());

否则默认路由器将处理错误,就像您注意到的那样。

如果您想为默认路由器使用主体解析器中间件,请确保在您添加testRouter:

app.use('/test', testRouter);
app.use(bodyParser.json());

是我的问题的答案,如何在路由器的 errorHandler 中捕获 bodyParser 错误。然而,我发现了一个稍微不同的解决方案 without catching the error inside the router。我的基本想法是,我想将与 /api/v1.0 下公开的 api 相关的所有内容放入 javascript 模块中的路由器中——包括一个错误处理程序,它以api。因此我在 app.js 中有以下行:

app.use('/api/v1.0', require('./routes/api/v1.0/api'));

api.js 导出一个 express.Router()。该路由器永远不会处理来自路由器 'outside' 的错误。 (另请参阅 GitHub 个问题 catch error of "toplevel" app.use-middlewear in router error handler #2679 and Inconsistent behavior with error-handling middleware in routers #2633)。

要使用 api 特定错误处理程序捕获所有错误,必须将 api 路由器和 api 错误处理程序分开。可以这样做:

api.js:

var express = require('express');
var router = express.Router();

router.use('/endpoint', require('./endpoint'));

var errorHandler = function (err, req, res, next) {
  // all errors need to be returned in json
  res.status(err.status || 500);
  res.json({ error: err.message });
};

module.exports.router = router;
module.exports.errorHandler = errorHandler;

app.js:

var api = require('./routes/api/v1.0/api');
app.use('/api/v1.0', api.router);
app.use('/api/v1.0', api.errorHandler);

这样 api 的错误处理程序仍然只处理对 /api/v1.0 的请求,但可以捕获所有错误,包括例如来自定义为应用程序级中间件的 bodyParser 的错误。