【发布时间】:2013-05-10 22:05:36
【问题描述】:
我试图通过仅根据请求的路径调用某些中间件函数来缩短我的 Express/Connect 中间件管道。
但是,以下操作会失败:
_cookieParser(req, res, function(err) {
if(err) return next(err);
_session(req, res, function(err) {
if(err) return next(err);
_csrf(req, res, function(err) {
if(err) return next(err);
loadUserFromSession(req, res, function(err) {
if(err) return next(err);
if(req.method == "POST") {
_bodyParser(req, res, next);
} else {
next();
}
});
});
});
});
但这会很好用:
_cookieParser(req, res, function(err) {
if(err) return next(err);
_session(req, res, function(err) {
if(err) return next(err);
_csrf(req, res, function(err) {
if(err) return next(err);
_bodyParser(req, res, function(err) {
if(err) return next(err);
loadUserFromSession(req, res, next);
});
});
});
});
loadUserFromSession 在哪里:
function loadUserFromSession(req, res, next) {
if(req.session && req.session.userId) {
userFunctions.getUserById(req.session.userId, function(err, user) {
if(err) return next(err);
if(user) {
req.user = user;
return next();
} else {
req.session.destroy();
return next(new Error('Unauthenticated'));
}
});
} else {
return next(new Error('Unauthenticated'));
}
};
为什么我不能在 loadUserFromSession() 之后调用 bodyParser()?
编辑
抱歉没有详细说明失败/意外结果。
如果我在 loadUserFromSession() 之后放置 bodyParser() 或只是 json()(因为 POST 内容是 json),则调用永远不会在 json() 内返回。如果我在 res.on('data') 或 res.on('end') 上的节点检查器中放置断点,都不会被触发。
json中间件的源码如下:
exports = module.exports = function(options){
var options = options || {}
, strict = options.strict !== false;
var limit = options.limit
? _limit(options.limit)
: noop;
return function json(req, res, next) {
if (req._body) return next();
req.body = req.body || {};
if (!utils.hasBody(req)) return next();
// check Content-Type
if ('application/json' != utils.mime(req)) return next();
// flag as parsed
req._body = true;
// parse
limit(req, res, function(err){
if (err) return next(err);
var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){
buf += chunk <==BREAKPOINT NEVER GETS CALLED
});
req.on('end', function(){
var first = buf.trim()[0]; <==BREAKPOINT NEVER GETS CALLED
if (0 == buf.length) {
return next(400, 'invalid json, empty body');
}
if (strict && '{' != first && '[' != first) return next(400, 'invalid json');
try {
req.body = JSON.parse(buf, options.reviver);
next();
} catch (err){
err.body = buf;
err.status = 400;
next(err);
}
});
});
}
};
【问题讨论】:
-
请编辑您的问题并将“将失败”替换为实际的错误消息和堆栈跟踪,或者如果失败不是错误,请描述错误行为。
-
旁注,使用中间件的嵌套方式较少。您上面所拥有的对于 express 来说是唯一的(礼貌地说)。如果您只想在某些路径中使用某些东西,请尝试
app.use('/some/path', someMiddleware),但实际上大多数中间件在不适用于当前请求时成本非常小。例如,bodyParser 只检查请求方法,如果没有正文,则立即调用next()。这不是你不应该尝试解决的问题。 -
@PeterLyons 添加了有关我的问题的更多详细信息。在结构上,我完全不同意你的看法。我走这条路,不是因为性能,而是安全。我不希望我的应用程序上传所有可以发布的文件。我有一些端点是公开的,有些不是。我不希望仅仅因为人们将文件上传到不应允许上传的端点而使我的应用程序超载(或 DDOS,如果它被知道的话)。
标签: express connect middleware