Skip to content

Commit

Permalink
Enable proxy response to have multiple Set-Cookie raw headers #1101
Browse files Browse the repository at this point in the history
  • Loading branch information
Kris Williams authored and jcrugzz committed Dec 4, 2016
1 parent c252b32 commit 8cb451f
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 21 deletions.
2 changes: 1 addition & 1 deletion examples/http/proxy-https-to-http.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var https = require('https'),
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello http over https\n');
res.end();
res.end();
}).listen(9009);

//
Expand Down
2 changes: 1 addition & 1 deletion examples/http/proxy-https-to-https.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var https = require('https'),
https.createServer(httpsOpts, function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
res.end();
}).listen(9010);

//
Expand Down
20 changes: 14 additions & 6 deletions lib/http-proxy/passes/web-outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,18 @@ module.exports = { // <--
*/
writeHeaders: function writeHeaders(req, res, proxyRes, options) {
var rewriteCookieDomainConfig = options.cookieDomainRewrite,
// In proxyRes.rawHeaders Set-Cookie headers are sparse.
// so, we'll collect Set-Cookie headers, and set them in the response as an array.
setCookies = [],
setHeader = function(key, header) {
if (header != undefined) {
if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') {
header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig);
}
res.setHeader(String(key).trim(), header);
if (header == undefined) return;
if (key.toLowerCase() !== 'set-cookie') {
return res.setHeader(String(key).trim(), header);
}
if (rewriteCookieDomainConfig) {
header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig);
}
setCookies.push(header); // defer to the end when we have all of them
};

if (typeof rewriteCookieDomainConfig === 'string') { //also test for ''
Expand All @@ -104,13 +109,16 @@ module.exports = { // <--
var key = proxyRes.rawHeaders[i];
var header = proxyRes.rawHeaders[i + 1];
setHeader(key, header);
};
}
} else {
Object.keys(proxyRes.headers).forEach(function(key) {
var header = proxyRes.headers[key];
setHeader(key, header);
});
}
if (setCookies.length) {
res.setHeader('Set-Cookie', setCookies.length === 1 ? setCookies[0] : setCookies);
}
},

/**
Expand Down
67 changes: 55 additions & 12 deletions test/lib-http-proxy-passes-web-outgoing-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,18 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
headers: {
hey: 'hello',
how: 'are you?',
'set-cookie': 'hello; domain=my.domain; path=/'
},
'set-cookie': [
'hello; domain=my.domain; path=/',
'there; domain=my.domain; path=/'
]
}
};
this.rawProxyRes = {
rawHeaders: [
'Hey', 'hello',
'How', 'are you?',
'Set-Cookie', 'hello; domain=my.domain; path=/'
'Set-Cookie', 'hello; domain=my.domain; path=/',
'Set-Cookie', 'there; domain=my.domain; path=/'
]
};
this.res = {
Expand All @@ -253,19 +259,35 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {

it('writes headers', function() {
var options = {};

httpProxy.writeHeaders({}, this.res, this.proxyRes, options);

expect(this.res.headers.hey).to.eql('hello');
expect(this.res.headers.how).to.eql('are you?');

expect(this.res.headers).to.have.key('set-cookie');
expect(this.res.headers['set-cookie']).to.be.an(Array);
expect(this.res.headers['set-cookie']).to.have.length(2);
});

it('writes raw headers', function() {
var options = {};
httpProxy.writeHeaders({}, this.res, this.rawProxyRes, options);

expect(this.res.headers.hey).to.eql('hello');
expect(this.res.headers.how).to.eql('are you?');

expect(this.res.headers).to.have.key('set-cookie');
expect(this.res.headers['set-cookie']).to.be.an(Array);
expect(this.res.headers['set-cookie']).to.have.length(2);
});

it('does not rewrite domain', function() {
var options = {};

httpProxy.writeHeaders({}, this.res, this.proxyRes, options);

expect(this.res.headers['set-cookie']).to.eql('hello; domain=my.domain; path=/');
expect(this.res.headers['set-cookie'])
.to.contain('hello; domain=my.domain; path=/');
});

it('rewrites domain', function() {
Expand All @@ -275,7 +297,8 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {

httpProxy.writeHeaders({}, this.res, this.proxyRes, options);

expect(this.res.headers['set-cookie']).to.eql('hello; domain=my.new.domain; path=/');
expect(this.res.headers['set-cookie'])
.to.contain('hello; domain=my.new.domain; path=/');
});

it('removes domain', function() {
Expand All @@ -285,7 +308,8 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {

httpProxy.writeHeaders({}, this.res, this.proxyRes, options);

expect(this.res.headers['set-cookie']).to.eql('hello; path=/');
expect(this.res.headers['set-cookie'])
.to.contain('hello; path=/');
});

it('rewrites headers with advanced configuration', function() {
Expand All @@ -301,14 +325,33 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
'hello-on-my.old.domain; domain=my.old.domain; path=/',
'hello-on-my.special.domain; domain=my.special.domain; path=/'
];
var setCookieValueIndex = this.proxyRes.rawHeaders.indexOf('Set-Cookie') + 1;
this.proxyRes.rawHeaders[setCookieValueIndex] = [
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);

expect(this.res.headers['set-cookie'])
.to.contain('hello-on-my.domain; path=/');
expect(this.res.headers['set-cookie'])
.to.contain('hello-on-my.old.domain; domain=my.new.domain; path=/');
expect(this.res.headers['set-cookie'])
.to.contain('hello-on-my.special.domain; domain=my.special.domain; path=/');
});

it('rewrites raw headers with advanced configuration', function() {
var options = {
cookieDomainRewrite: {
'*': '',
'my.old.domain': 'my.new.domain',
'my.special.domain': 'my.special.domain'
}
};
this.rawProxyRes.rawHeaders = this.rawProxyRes.rawHeaders.concat([
'Set-Cookie',
'hello-on-my.domain; domain=my.domain; path=/',
'Set-Cookie',
'hello-on-my.old.domain; domain=my.old.domain; path=/',
'Set-Cookie',
'hello-on-my.special.domain; domain=my.special.domain; path=/'
];

httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
]);
httpProxy.writeHeaders({}, this.res, this.rawProxyRes, options);

expect(this.res.headers['set-cookie'])
.to.contain('hello-on-my.domain; path=/');
Expand Down
2 changes: 1 addition & 1 deletion test/lib-https-proxy-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Object.defineProperty(gen, 'port', {

describe('lib/http-proxy.js', function() {
describe('HTTPS #createProxyServer', function() {
describe('HTTPS to HTTP', function () {
describe('HTTPS to HTTP', function () {
it('should proxy the request en send back the response', function (done) {
var ports = { source: gen.port, proxy: gen.port };
var source = http.createServer(function(req, res) {
Expand Down

0 comments on commit 8cb451f

Please sign in to comment.