【问题标题】:Invoking an asynchronous method inside a middleware in node-http-proxy在 node-http-proxy 的中间件中调用异步方法
【发布时间】:2012-07-25 05:11:47
【问题描述】:

我正在尝试在 Node.js 中使用 node-http-proxy 创建一个代理,以检查请求是否在 mongodb 中获得授权。

基本上,我为我使用的 node-http-proxy 创建了一个中间件模块,如下所示:

httpProxy.createServer(
require('./example-middleware')(),
9005, 'localhost'
).listen(8005)

中间件模块所做的是使用 mongojs 连接到 mongodb 并运行查询以查看用户是否有权访问资源:

module.exports = function(){
// Do something when first loaded!
console.log("Middleware loaded!");

return function (req, res, next) {
var record = extractCredentials(req);
var query = -- Db query --

//Debug:
log("Query result", query);

db.authList.find(query).sort({
    "url.len": -1
}, function(err, docs){
    console.log(docs);

    // Return the creator for the longest matching path:
    if(docs.length > 0) {
        console.log("User confirmed!");
        next();
    } else {
        console.log("User not confirmed!");
        res.writeHead(403, {
            'Content-Type': 'text/plain'
        });
        res.write('You are not allowed to access this resource...');
        res.end();
    }

});

}
}

现在的问题是,一旦我使用 mongojs 添加对 mongodb 的异步调用,代理就会挂起并且永远不会发回响应。

澄清:在“用户未确认”上,一切正常,并返回 403。在“用户确认”上,但是我看到了日志,但浏览器然后永远挂起并且请求没有被代理。

现在,如果我在回调之外删除“用户确认”和 next() 部分,它确实有效:

module.exports = function(){
// Do something when first loaded!
console.log("Middleware loaded!");

return function (req, res, next) {
    var record = extractCredentials(req);
    var query = --- query ---


    console.log("User confirmed!");
    next();
}

但我不能这样做,因为 mongojs 查询意味着(我猜是正确的)异步执行,只有当数据库回复时才会触发回调......

我也试过不使用中间件的版本:

http.createServer(function (req, res) {
  // run the async query here!
  proxy.proxyRequest(req, res, {
  host: 'localhost',
  port: 9000
});
}).listen(8001);

但这也无济于事......

有什么线索吗?请注意,我是 node.js 的新手,所以我怀疑我的理解有误...

【问题讨论】:

  • 你用的是什么中间件?连接?

标签: node.js asynccallback node-http-proxy


【解决方案1】:

找到了答案,其实问题是请求需要被缓冲:

httpProxy.createServer(function (req, res, proxy) {
// ignore favicon
if (req.url === '/favicon.ico') {
    res.writeHead(200, {
        'Content-Type': 'image/x-icon'
    } );
    res.end();
    console.log('favicon requested');
    return;
}

var credentials = extractCredentials(req);
console.log(credentials);

var buffer = httpProxy.buffer(req);

checkRequest(credentials, function(user){
    if(user == ...) {
        console.log("Access granted!");
        proxy.proxyRequest(req, res, {
            host: 'localhost',
            port: 9005, 
            buffer: buffer
        });
    } else {
        console.log("Access denied!");
        res.writeHead(403, {
            "Content-Type": "text/plain"
        });
        res.write("You are not allowed to access this resource...");
        res.end();
    }

});

}).listen(8005);

【讨论】:

  • 但是你怎么会在中间件中,作为代理对象它仍然不可用(因为在你声明包含“代理”参数的函数之前加载了中间件)?
【解决方案2】:

两个问题:

  1. 您没有在 else 情况下调用 next(); sort 回调。
  2. sort 回调的第二个参数是Cursor,而不是文档数组。因此,docs.length > 0 永远不会为真,代码始终遵循 else 路径。

【讨论】:

  • 嗨!谢谢。我想我的问题不够清楚,所以我编辑了它(我的错!)。我确实在 else 子句中调用了写响应(请参阅新的编辑),排序的第二个参数是回调而不是游标,正如我所说我使用的是 mongojs 而不是本机 mongo javascript 驱动程序(查询工作正常)。
  • 啊,没问题;我错过了这个代理部分的坏处。您的 node-http-proxy 中间件函数的第三个参数不是 proxy 对象,而不是 next 函数吗? github.com/nodejitsu/node-http-proxy/…
  • 显然它是一个 next() 函数。我尝试使用代理,但结果相同:两者都是 proxy.proxyRequest(req, res);和下一个();在回调之外工作,但不在回调内部。代理仍然挂起...
猜你喜欢
  • 1970-01-01
  • 2014-04-19
  • 2016-02-07
  • 1970-01-01
  • 2023-03-23
  • 2015-11-09
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
相关资源
最近更新 更多