【问题标题】:Transfer cookies across domains in express在 express 中跨域传输 cookie
【发布时间】:2014-08-08 04:29:46
【问题描述】:

我在 nodejs 中设置了一个代理,它可以连接到我们的一个后端服务器获取数据;其中一些数据(例如会话 ID)存储为 cookie。我想要做的是让代理获取远程cookie,然后将其推送到原始请求的响应标头中,然后将响应发回。我很接近,但遇到了障碍:

app.get(/\/json\/(.+)/, getJson);

var getJson = function(req, response1) {
    response1.setHeader('Content-Type', 'application/json; charset=utf-8');

    var before1stWrite = true;
    utils.setCookies(response1, ["floo=flum"])   // this works

    var options = {
        host : config.scraperUrl.replace('http://', ''),
        path : '/rwd/' + req.params[0] + '?' + querystring.stringify(req.query),
        method : "GET",
        rejectUnauthorized : false
    };

    var request = https.request(options, function(response2) {
        response2.setEncoding('utf8');
        // utils.setCookies(response1, ["flib=flah"])      // this fails, too

        response2.on('data', function(d) {
            if (before1stWrite) {
              console.log(response2.headers['set-cookie']);   // remote's cookies
              utils.setCookies(response1, ["flib=flah"])      // this fails
              before1stWrite = false;
            }
            response1.write(d);
        });

        response2.on('end', function() {
            response1.end()
        });
    });

    request.end();

    request.on('error', function(e) {
        console.error("error occurred: " + e.message);
        response1.end();
    });
}

setCookies(response1, cookies) 只是循环通过 cookie 并执行 res.setHeader('Set-Cookie', cookie)

问题在于,在调用第二个 setCookies 时,标头似乎已经烘焙;将方法移至“数据”事件处理程序无济于事。我得到的错误是:

http.js:689
    throw new Error('Can\'t set headers after they are sent.');

有什么方法可以将标头添加到我从 response2 收到的 response1 中?


更新

我修复了代码以确保尝试写入 response1 的标头在任何其他写入之前完成;然而,这不是解决办法。

【问题讨论】:

    标签: javascript node.js cookies express


    【解决方案1】:

    是的,您不能在数据开始流动后发送标头。您是否尝试在此行之后设置标题?

    response.setEncoding('utf8');
    

    另外,您是否考虑过使用流而不是分块传输? http://nodejs.org/api/stream.html

    【讨论】:

    • 我没有在收到的响应中设置标题,我试图在传入的 res 中设置它。我怀疑 app.get() 一旦返回,就已经写入了标题在第一个响应对象 (res) 上。无论如何,我可以在 setEncoding 下面的行中调用 response.headers['set-cookie'],但仍然无法写入原始的传入 res 标头。同样的错误。
    【解决方案2】:

    您需要缓冲数据。 这样做很像管道:

            response.on('data', function(d) {
              res.write(d);
            });
    

    所以您会立即发送回复。没试过,但这应该可以:

    var data = "";
    response.on('data', function(d) {
      data += d;
    });
    
    response.on('end', function() {
        console.log(response.headersSent);
        console.log(response.headers['set-cookie']);
        utils.setCookies(res, ["flib=flah"])
        res.write(data);
        res.end();
    });
    

    请记住,您正在将所有数据缓冲到内存中,不建议用于大型响应。

    【讨论】:

    • 不,这也不起作用。我正在澄清我的示例: response1 是我传递给 getJSON 方法的响应; response2 是我从 getJSON 方法中的调用返回的响应;我没有从 response1 中读取,但我正在尝试根据我从 response2 返回的内容更新 response1 上的标头。阅读更多内容,这可能是一个中间件问题,其中标头被写入但未遵循正确的协议。
    • 是的,我已经考虑过了。但我认为 app.get() 中的问题是在调用回调函数之前烘焙标头。猜测,但这似乎正在发生。如果我可以进行肮脏的同步调用,我可以确定。
    猜你喜欢
    • 2012-06-05
    • 2021-03-05
    • 2015-05-28
    • 2011-03-21
    • 2012-01-19
    • 2013-09-15
    相关资源
    最近更新 更多