diff --git a/examples/http/proxy-https-to-http.js b/examples/http/proxy-https-to-http.js index 227f4373e..5eb07a14c 100644 --- a/examples/http/proxy-https-to-http.js +++ b/examples/http/proxy-https-to-http.js @@ -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); // diff --git a/examples/http/proxy-https-to-https.js b/examples/http/proxy-https-to-https.js index 4cfe0c18c..e600f389c 100644 --- a/examples/http/proxy-https-to-https.js +++ b/examples/http/proxy-https-to-https.js @@ -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); // diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index 0c71e54ea..e7dc479f8 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -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 '' @@ -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); + } }, /** diff --git a/test/lib-http-proxy-passes-web-outgoing-test.js b/test/lib-http-proxy-passes-web-outgoing-test.js index 6a3ec2230..451f61419 100644 --- a/test/lib-http-proxy-passes-web-outgoing-test.js +++ b/test/lib-http-proxy-passes-web-outgoing-test.js @@ -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 = { @@ -253,11 +259,26 @@ 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() { @@ -265,7 +286,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.domain; path=/'); + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain; path=/'); }); it('rewrites domain', function() { @@ -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() { @@ -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() { @@ -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=/'); diff --git a/test/lib-https-proxy-test.js b/test/lib-https-proxy-test.js index e0634cd52..a44fadbf8 100644 --- a/test/lib-https-proxy-test.js +++ b/test/lib-https-proxy-test.js @@ -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) {