From ff57a462eb5c8177dff90aeda621167a6d95db71 Mon Sep 17 00:00:00 2001 From: Yuta Shimizu Date: Thu, 1 Dec 2016 12:29:13 +0900 Subject: [PATCH 1/3] Keep original letter case of response header keys --- lib/http-proxy/passes/web-outgoing.js | 7 ++++--- ...lib-http-proxy-passes-web-outgoing-test.js | 19 ++++++++++++++++--- test/lib-http-proxy-test.js | 3 +++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index e2d957f51..653098f8b 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -87,15 +87,16 @@ module.exports = { // <-- if (typeof rewriteCookieDomainConfig === 'string') { //also test for '' rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig }; } - Object.keys(proxyRes.headers).forEach(function(key) { - var header = proxyRes.headers[key]; + for (var i = 0; i < proxyRes.rawHeaders.length; i += 2) { + var key = proxyRes.rawHeaders[i]; + var header = proxyRes.rawHeaders[i + 1]; if (header != undefined) { if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); } res.setHeader(String(key).trim(), header); } - }); + }; }, /** diff --git a/test/lib-http-proxy-passes-web-outgoing-test.js b/test/lib-http-proxy-passes-web-outgoing-test.js index c636e2027..6a3ec2230 100644 --- a/test/lib-http-proxy-passes-web-outgoing-test.js +++ b/test/lib-http-proxy-passes-web-outgoing-test.js @@ -234,11 +234,18 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () { hey: 'hello', how: 'are you?', 'set-cookie': 'hello; domain=my.domain; path=/' - } + }, + rawHeaders: [ + 'Hey', 'hello', + 'How', 'are you?', + 'Set-Cookie', 'hello; domain=my.domain; path=/' + ] }; this.res = { setHeader: function(k, v) { - this.headers[k] = v; + // https://nodejs.org/api/http.html#http_message_headers + // Header names are lower-cased + this.headers[k.toLowerCase()] = v; }, headers: {} }; @@ -260,7 +267,7 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () { expect(this.res.headers['set-cookie']).to.eql('hello; domain=my.domain; path=/'); }); - + it('rewrites domain', function() { var options = { cookieDomainRewrite: 'my.new.domain' @@ -294,6 +301,12 @@ 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] = [ + 'hello-on-my.domain; domain=my.domain; path=/', + 'hello-on-my.old.domain; domain=my.old.domain; path=/', + 'hello-on-my.special.domain; domain=my.special.domain; path=/' + ]; httpProxy.writeHeaders({}, this.res, this.proxyRes, options); diff --git a/test/lib-http-proxy-test.js b/test/lib-http-proxy-test.js index bd28483b4..6e3be50a1 100644 --- a/test/lib-http-proxy-test.js +++ b/test/lib-http-proxy-test.js @@ -148,6 +148,9 @@ describe('lib/http-proxy.js', function() { method: 'GET' }, function(res) { expect(res.statusCode).to.eql(200); + expect(res.headers['content-type']).to.eql('text/plain'); + expect(res.rawHeaders.indexOf('Content-Type')).not.to.eql(-1); + expect(res.rawHeaders.indexOf('text/plain')).not.to.eql(-1); res.on('data', function (data) { expect(data.toString()).to.eql('Hello from ' + ports.source); From d3d7cc25a3f107de4043ea7b379dba16b325806d Mon Sep 17 00:00:00 2001 From: Yuta Shimizu Date: Thu, 1 Dec 2016 15:35:13 +0900 Subject: [PATCH 2/3] Support node older than v0.11.6 messege.rawHeaders was added in v0.11.6 --- lib/http-proxy/passes/web-outgoing.js | 32 +++++++++++++++++++-------- test/lib-http-proxy-test.js | 6 +++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index 653098f8b..f40599036 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -87,16 +87,30 @@ module.exports = { // <-- if (typeof rewriteCookieDomainConfig === 'string') { //also test for '' rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig }; } - for (var i = 0; i < proxyRes.rawHeaders.length; i += 2) { - var key = proxyRes.rawHeaders[i]; - var header = proxyRes.rawHeaders[i + 1]; - if (header != undefined) { - if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { - header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); + // message.rawHeaders is added in: v0.11.6 + // https://nodejs.org/api/http.html#http_message_rawheaders + if (proxyRes.rawHeaders != undefined) { + for (var i = 0; i < proxyRes.rawHeaders.length; i += 2) { + var key = proxyRes.rawHeaders[i]; + var header = proxyRes.rawHeaders[i + 1]; + if (header != undefined) { + if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { + header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); + } + res.setHeader(String(key).trim(), header); } - res.setHeader(String(key).trim(), header); - } - }; + }; + } else { + Object.keys(proxyRes.headers).forEach(function(key) { + var header = proxyRes.headers[key]; + if (header != undefined) { + if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { + header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); + } + res.setHeader(String(key).trim(), header); + } + }); + } }, /** diff --git a/test/lib-http-proxy-test.js b/test/lib-http-proxy-test.js index 6e3be50a1..8b024c9f1 100644 --- a/test/lib-http-proxy-test.js +++ b/test/lib-http-proxy-test.js @@ -149,8 +149,10 @@ describe('lib/http-proxy.js', function() { }, function(res) { expect(res.statusCode).to.eql(200); expect(res.headers['content-type']).to.eql('text/plain'); - expect(res.rawHeaders.indexOf('Content-Type')).not.to.eql(-1); - expect(res.rawHeaders.indexOf('text/plain')).not.to.eql(-1); + if (res.rawHeaders != undefined) { + expect(res.rawHeaders.indexOf('Content-Type')).not.to.eql(-1); + expect(res.rawHeaders.indexOf('text/plain')).not.to.eql(-1); + } res.on('data', function (data) { expect(data.toString()).to.eql('Hello from ' + ports.source); From 605a05fc8cbfa2ea27a77ccc639b6944ec03b9c4 Mon Sep 17 00:00:00 2001 From: Yuta Shimizu Date: Fri, 2 Dec 2016 09:51:38 +0900 Subject: [PATCH 3/3] Extract duplicated logic to method --- lib/http-proxy/passes/web-outgoing.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index f40599036..0c71e54ea 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -83,32 +83,32 @@ module.exports = { // <-- * @api private */ writeHeaders: function writeHeaders(req, res, proxyRes, options) { - var rewriteCookieDomainConfig = options.cookieDomainRewrite; + var rewriteCookieDomainConfig = options.cookieDomainRewrite, + 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 (typeof rewriteCookieDomainConfig === 'string') { //also test for '' rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig }; } + // message.rawHeaders is added in: v0.11.6 // https://nodejs.org/api/http.html#http_message_rawheaders if (proxyRes.rawHeaders != undefined) { for (var i = 0; i < proxyRes.rawHeaders.length; i += 2) { var key = proxyRes.rawHeaders[i]; var header = proxyRes.rawHeaders[i + 1]; - if (header != undefined) { - if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { - header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); - } - res.setHeader(String(key).trim(), header); - } + setHeader(key, header); }; } else { Object.keys(proxyRes.headers).forEach(function(key) { var header = proxyRes.headers[key]; - if (header != undefined) { - if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { - header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); - } - res.setHeader(String(key).trim(), header); - } + setHeader(key, header); }); } },