Jeff Lowery
Jeff Lowery

Reputation: 2597

Transfer cookies across domains in express

I've got a proxy set up in nodejs that goes to one of our backend servers for data; some of that data (such as session id) is stored as cookies. what I want to do is have the proxy get the remote cookies, push then into the header of the response to the original request, then send the response back. I'm close, but hit a snag:

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) just loops thru the cookies and does res.setHeader('Set-Cookie', cookie)

The problem is that it looks like the headers have been baked by the time the second setCookies is called; moving the method to the 'data' event handler does not help. The error I get is:

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

Any way to add headers to response1 that I receive from the response2?


UPDATE

I fixed the code to be sure that the attempt to write to headers of response1 was done before any other writes; it is not a fix, however.

Upvotes: 0

Views: 954

Answers (2)

Maroshii
Maroshii

Reputation: 4017

You'll need to buffer the data. Doing this is pretty much like piping:

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

so you're sending the response straight away. Haven't tried it but this should work:

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();
});

Just remember you're buffering all that data into memory, not recommended for large responses.

Upvotes: 1

Rajkumar Madhuram
Rajkumar Madhuram

Reputation: 684

Yes, you cannot send headers after data has started flowing. Did you try setting the header after this line?

response.setEncoding('utf8');

Also, did you consider using streams rather than transferring in chunks? http://nodejs.org/api/stream.html

Upvotes: 1

Related Questions