mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
cookieDomainRewrite option (#1009)
This commit is contained in:
parent
9d06ca99d3
commit
1e52f660f0
12
README.md
12
README.md
@ -337,6 +337,18 @@ proxyServer.listen(8015);
|
|||||||
* **hostRewrite**: rewrites the location hostname on (201/301/302/307/308) redirects.
|
* **hostRewrite**: rewrites the location hostname on (201/301/302/307/308) redirects.
|
||||||
* **autoRewrite**: rewrites the location host/port on (201/301/302/307/308) redirects based on requested host/port. Default: false.
|
* **autoRewrite**: rewrites the location host/port on (201/301/302/307/308) redirects based on requested host/port. Default: false.
|
||||||
* **protocolRewrite**: rewrites the location protocol on (201/301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
* **protocolRewrite**: rewrites the location protocol on (201/301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
||||||
|
* **cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
|
||||||
|
* `false` (default): disable cookie rewriting
|
||||||
|
* String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.
|
||||||
|
* Object: mapping of domains to new domains, use `"*"` to match all domains.
|
||||||
|
For example keep one domain unchanged, rewrite one domain and remove other domains:
|
||||||
|
```
|
||||||
|
cookieDomainRewrite: {
|
||||||
|
"unchanged.domain": "unchanged.domain",
|
||||||
|
"old.domain": "new.domain",
|
||||||
|
"*": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
* **headers**: object with extra headers to be added to target requests.
|
* **headers**: object with extra headers to be added to target requests.
|
||||||
|
|
||||||
**NOTE:**
|
**NOTE:**
|
||||||
|
|||||||
@ -4,7 +4,8 @@ var common = exports,
|
|||||||
required = require('requires-port');
|
required = require('requires-port');
|
||||||
|
|
||||||
var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i,
|
var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i,
|
||||||
isSSL = /^https|wss/;
|
isSSL = /^https|wss/,
|
||||||
|
cookieDomainRegex = /(;\s*domain=)([^;]+)/i;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple Regex for testing if protocol is https
|
* Simple Regex for testing if protocol is https
|
||||||
@ -201,6 +202,41 @@ common.urlJoin = function() {
|
|||||||
return retSegs.join('?')
|
return retSegs.join('?')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrites or removes the domain of a cookie header
|
||||||
|
*
|
||||||
|
* @param {String|Array} Header
|
||||||
|
* @param {Object} Config, mapping of domain to rewritten domain.
|
||||||
|
* '*' key to match any domain, null value to remove the domain.
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
common.rewriteCookieDomain = function rewriteCookieDomain(header, config) {
|
||||||
|
if (Array.isArray(header)) {
|
||||||
|
return header.map(function (headerElement) {
|
||||||
|
return rewriteCookieDomain(headerElement, config);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return header.replace(cookieDomainRegex, function(match, prefix, previousDomain) {
|
||||||
|
var newDomain;
|
||||||
|
if (previousDomain in config) {
|
||||||
|
newDomain = config[previousDomain];
|
||||||
|
} else if ('*' in config) {
|
||||||
|
newDomain = config['*'];
|
||||||
|
} else {
|
||||||
|
//no match, return previous domain
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
if (newDomain) {
|
||||||
|
//replace domain
|
||||||
|
return prefix + newDomain;
|
||||||
|
} else {
|
||||||
|
//remove domain
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the host and see if it potentially has a port in it (keep it simple)
|
* Check the host and see if it potentially has a port in it (keep it simple)
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
var url = require('url'),
|
var url = require('url'),
|
||||||
|
common = require('../common'),
|
||||||
passes = exports;
|
passes = exports;
|
||||||
|
|
||||||
var redirectRegex = /^201|30(1|2|7|8)$/;
|
var redirectRegex = /^201|30(1|2|7|8)$/;
|
||||||
@ -77,13 +78,22 @@ var redirectRegex = /^201|30(1|2|7|8)$/;
|
|||||||
* @param {ClientRequest} Req Request object
|
* @param {ClientRequest} Req Request object
|
||||||
* @param {IncomingMessage} Res Response object
|
* @param {IncomingMessage} Res Response object
|
||||||
* @param {proxyResponse} Res Response object from the proxy request
|
* @param {proxyResponse} Res Response object from the proxy request
|
||||||
|
* @param {Object} Options options.cookieDomainRewrite: Config to rewrite cookie domain
|
||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
function writeHeaders(req, res, proxyRes) {
|
function writeHeaders(req, res, proxyRes, options) {
|
||||||
|
var rewriteCookieDomainConfig = options.cookieDomainRewrite;
|
||||||
|
if (typeof rewriteCookieDomainConfig === 'string') { //also test for ''
|
||||||
|
rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig };
|
||||||
|
}
|
||||||
Object.keys(proxyRes.headers).forEach(function(key) {
|
Object.keys(proxyRes.headers).forEach(function(key) {
|
||||||
if(proxyRes.headers[key] != undefined){
|
var header = proxyRes.headers[key];
|
||||||
res.setHeader(String(key).trim(), proxyRes.headers[key]);
|
if (header != undefined) {
|
||||||
|
if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') {
|
||||||
|
header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig);
|
||||||
|
}
|
||||||
|
res.setHeader(String(key).trim(), header);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,23 +6,23 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.req = {
|
this.req = {
|
||||||
headers: {
|
headers: {
|
||||||
host: "ext-auto.com"
|
host: 'ext-auto.com'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.proxyRes = {
|
this.proxyRes = {
|
||||||
statusCode: 301,
|
statusCode: 301,
|
||||||
headers: {
|
headers: {
|
||||||
location: "http://backend.com/"
|
location: 'http://backend.com/'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.options = {
|
this.options = {
|
||||||
target: "http://backend.com"
|
target: 'http://backend.com'
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
context('rewrites location host with hostRewrite', function() {
|
context('rewrites location host with hostRewrite', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.options.hostRewrite = "ext-manual.com";
|
this.options.hostRewrite = 'ext-manual.com';
|
||||||
});
|
});
|
||||||
[201, 301, 302, 307, 308].forEach(function(code) {
|
[201, 301, 302, 307, 308].forEach(function(code) {
|
||||||
it('on ' + code, function() {
|
it('on ' + code, function() {
|
||||||
@ -52,14 +52,14 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
|||||||
|
|
||||||
it('not when the redirected location does not match target host', function() {
|
it('not when the redirected location does not match target host', function() {
|
||||||
this.proxyRes.statusCode = 302;
|
this.proxyRes.statusCode = 302;
|
||||||
this.proxyRes.headers.location = "http://some-other/";
|
this.proxyRes.headers.location = 'http://some-other/';
|
||||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||||
expect(this.proxyRes.headers.location).to.eql('http://some-other/');
|
expect(this.proxyRes.headers.location).to.eql('http://some-other/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('not when the redirected location does not match target port', function() {
|
it('not when the redirected location does not match target port', function() {
|
||||||
this.proxyRes.statusCode = 302;
|
this.proxyRes.statusCode = 302;
|
||||||
this.proxyRes.headers.location = "http://backend.com:8080/";
|
this.proxyRes.headers.location = 'http://backend.com:8080/';
|
||||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||||
expect(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
|
expect(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
|
||||||
});
|
});
|
||||||
@ -91,14 +91,14 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
|||||||
|
|
||||||
it('not when the redirected location does not match target host', function() {
|
it('not when the redirected location does not match target host', function() {
|
||||||
this.proxyRes.statusCode = 302;
|
this.proxyRes.statusCode = 302;
|
||||||
this.proxyRes.headers.location = "http://some-other/";
|
this.proxyRes.headers.location = 'http://some-other/';
|
||||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||||
expect(this.proxyRes.headers.location).to.eql('http://some-other/');
|
expect(this.proxyRes.headers.location).to.eql('http://some-other/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('not when the redirected location does not match target port', function() {
|
it('not when the redirected location does not match target port', function() {
|
||||||
this.proxyRes.statusCode = 302;
|
this.proxyRes.statusCode = 302;
|
||||||
this.proxyRes.headers.location = "http://backend.com:8080/";
|
this.proxyRes.headers.location = 'http://backend.com:8080/';
|
||||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||||
expect(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
|
expect(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
|
||||||
});
|
});
|
||||||
@ -129,13 +129,13 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('works together with hostRewrite', function() {
|
it('works together with hostRewrite', function() {
|
||||||
this.options.hostRewrite = 'ext-manual.com'
|
this.options.hostRewrite = 'ext-manual.com';
|
||||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||||
expect(this.proxyRes.headers.location).to.eql('https://ext-manual.com/');
|
expect(this.proxyRes.headers.location).to.eql('https://ext-manual.com/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works together with autoRewrite', function() {
|
it('works together with autoRewrite', function() {
|
||||||
this.options.autoRewrite = true
|
this.options.autoRewrite = true;
|
||||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||||
expect(this.proxyRes.headers.location).to.eql('https://ext-auto.com/');
|
expect(this.proxyRes.headers.location).to.eql('https://ext-auto.com/');
|
||||||
});
|
});
|
||||||
@ -199,31 +199,89 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
|||||||
writeHead: function(n) {
|
writeHead: function(n) {
|
||||||
expect(n).to.eql(200);
|
expect(n).to.eql(200);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
httpProxy.writeStatusCode({}, res, { statusCode: 200 });
|
httpProxy.writeStatusCode({}, res, { statusCode: 200 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#writeHeaders', function() {
|
describe('#writeHeaders', function() {
|
||||||
var proxyRes = {
|
beforeEach(function() {
|
||||||
headers: {
|
this.proxyRes = {
|
||||||
hey: 'hello',
|
headers: {
|
||||||
how: 'are you?'
|
hey: 'hello',
|
||||||
}
|
how: 'are you?',
|
||||||
};
|
'set-cookie': 'hello; domain=my.domain; path=/'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.res = {
|
||||||
|
setHeader: function(k, v) {
|
||||||
|
this.headers[k] = v;
|
||||||
|
},
|
||||||
|
headers: {}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
var res = {
|
it('writes headers', function() {
|
||||||
setHeader: function(k, v) {
|
var options = {};
|
||||||
this.headers[k] = v;
|
|
||||||
},
|
|
||||||
headers: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
httpProxy.writeHeaders({}, res, proxyRes);
|
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||||
|
|
||||||
expect(res.headers.hey).to.eql('hello');
|
expect(this.res.headers.hey).to.eql('hello');
|
||||||
expect(res.headers.how).to.eql('are you?');
|
expect(this.res.headers.how).to.eql('are you?');
|
||||||
|
});
|
||||||
|
|
||||||
|
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=/');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rewrites domain', function() {
|
||||||
|
var options = {
|
||||||
|
cookieDomainRewrite: 'my.new.domain'
|
||||||
|
};
|
||||||
|
|
||||||
|
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||||
|
|
||||||
|
expect(this.res.headers['set-cookie']).to.eql('hello; domain=my.new.domain; path=/');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes domain', function() {
|
||||||
|
var options = {
|
||||||
|
cookieDomainRewrite: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||||
|
|
||||||
|
expect(this.res.headers['set-cookie']).to.eql('hello; path=/');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rewrites headers with advanced configuration', function() {
|
||||||
|
var options = {
|
||||||
|
cookieDomainRewrite: {
|
||||||
|
'*': '',
|
||||||
|
'my.old.domain': 'my.new.domain',
|
||||||
|
'my.special.domain': 'my.special.domain'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.proxyRes.headers['set-cookie'] = [
|
||||||
|
'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);
|
||||||
|
|
||||||
|
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=/');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user