diff --git a/README.md b/README.md index 40367e111..d7b06c583 100644 --- a/README.md +++ b/README.md @@ -350,6 +350,18 @@ proxyServer.listen(8015); "*": "" } ``` +* **cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values: + * `false` (default): disable cookie rewriting + * String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`. + * Object: mapping of paths to new paths, use `"*"` to match all paths. + For example keep one path unchanged, rewrite one path and remove other paths: + ``` + cookiePathRewrite: { + "/unchanged.path/": "/unchanged.path/", + "/old.path/": "/new.path/", + "*": "" + } + ``` * **headers**: object with extra headers to be added to target requests. * **proxyTimeout**: timeout (in millis) when proxy receives no response from target diff --git a/lib/http-proxy/common.js b/lib/http-proxy/common.js index aa9700234..b2f302cad 100644 --- a/lib/http-proxy/common.js +++ b/lib/http-proxy/common.js @@ -4,8 +4,7 @@ var common = exports, required = require('requires-port'); var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i, - isSSL = /^https|wss/, - cookieDomainRegex = /(;\s*domain=)([^;]+)/i; + isSSL = /^https|wss/; /** * Simple Regex for testing if protocol is https @@ -211,27 +210,27 @@ common.urlJoin = function() { * * @api private */ -common.rewriteCookieDomain = function rewriteCookieDomain(header, config) { +common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) { if (Array.isArray(header)) { return header.map(function (headerElement) { - return rewriteCookieDomain(headerElement, config); + return rewriteCookieProperty(headerElement, config, property); }); } - return header.replace(cookieDomainRegex, function(match, prefix, previousDomain) { - var newDomain; - if (previousDomain in config) { - newDomain = config[previousDomain]; + return header.replace(new RegExp("(;\\s*" + property + "=)([^;]+)", 'i'), function(match, prefix, previousValue) { + var newValue; + if (previousValue in config) { + newValue = config[previousValue]; } else if ('*' in config) { - newDomain = config['*']; + newValue = config['*']; } else { - //no match, return previous domain + //no match, return previous value return match; } - if (newDomain) { - //replace domain - return prefix + newDomain; + if (newValue) { + //replace value + return prefix + newValue; } else { - //remove domain + //remove value return ''; } }); diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index cff86a700..05ded881c 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -84,12 +84,16 @@ module.exports = { // <-- */ writeHeaders: function writeHeaders(req, res, proxyRes, options) { var rewriteCookieDomainConfig = options.cookieDomainRewrite, + rewriteCookiePathConfig = options.cookiePathRewrite, preserveHeaderKeyCase = options.preserveHeaderKeyCase, rawHeaderKeyMap, setHeader = function(key, header) { if (header == undefined) return; if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { - header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); + header = common.rewriteCookieProperty(header, rewriteCookieDomainConfig, 'domain'); + } + if (rewriteCookiePathConfig && key.toLowerCase() === 'set-cookie') { + header = common.rewriteCookieProperty(header, rewriteCookiePathConfig, 'path'); } res.setHeader(String(key).trim(), header); }; @@ -98,6 +102,10 @@ module.exports = { // <-- rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig }; } + if (typeof rewriteCookiePathConfig === 'string') { //also test for '' + rewriteCookiePathConfig = { '*': rewriteCookiePathConfig }; + } + // message.rawHeaders is added in: v0.11.6 // https://nodejs.org/api/http.html#http_message_rawheaders if (preserveHeaderKeyCase && proxyRes.rawHeaders != undefined) { diff --git a/test/lib-http-proxy-passes-web-outgoing-test.js b/test/lib-http-proxy-passes-web-outgoing-test.js index ae86904da..a509cf1ae 100644 --- a/test/lib-http-proxy-passes-web-outgoing-test.js +++ b/test/lib-http-proxy-passes-web-outgoing-test.js @@ -289,6 +289,37 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () { expect(this.res.headers['set-cookie']).to.have.length(2); }); + it('rewrites path', function() { + var options = { + cookiePathRewrite: '/dummyPath' + }; + + httpProxy.writeHeaders({}, this.res, this.proxyRes, options); + + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain; path=/dummyPath'); + }); + + it('does not rewrite path', function() { + var options = {}; + + httpProxy.writeHeaders({}, this.res, this.proxyRes, options); + + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain; path=/'); + }); + + it('removes path', function() { + var options = { + cookiePathRewrite: '' + }; + + httpProxy.writeHeaders({}, this.res, this.proxyRes, options); + + expect(this.res.headers['set-cookie']) + .to.contain('hello; domain=my.domain'); + }); + it('does not rewrite domain', function() { var options = {};