diff --git a/README.md b/README.md index 1943f3f30..45d6e0ca8 100644 --- a/README.md +++ b/README.md @@ -325,6 +325,7 @@ proxyServer.listen(8015); * **secure**: true/false, if you want to verify the SSL Certs * **xfwd**: true/false, adds x-forward headers * **toProxy**: passes the absolute URL as the `path` (useful for proxying to proxies) + * **hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects. If you are using the `proxyServer.listen` method, the following options are also applicable: diff --git a/lib/http-proxy.js b/lib/http-proxy.js index 9a7f81ba7..b1ad646f4 100644 --- a/lib/http-proxy.js +++ b/lib/http-proxy.js @@ -41,6 +41,7 @@ module.exports.createProxyServer = * prependPath: * localAddress : * changeOrigin: + * hostRewrite: rewrites the location hostname on (301/302/307/308) redirects, Default: null. * } * * NOTE: `options.ws` and `options.ssl` are optional. diff --git a/lib/http-proxy/passes/web-incoming.js b/lib/http-proxy/passes/web-incoming.js index 572c11a8c..e8e84191b 100644 --- a/lib/http-proxy/passes/web-incoming.js +++ b/lib/http-proxy/passes/web-incoming.js @@ -144,7 +144,7 @@ web_o = Object.keys(web_o).map(function(pass) { proxyReq.on('response', function(proxyRes) { if(server) { server.emit('proxyRes', proxyRes, req, res); } for(var i=0; i < web_o.length; i++) { - if(web_o[i](req, res, proxyRes)) { break; } + if(web_o[i](req, res, proxyRes, options)) { break; } } // Allow us to listen when the proxy has completed diff --git a/lib/http-proxy/passes/web-outgoing.js b/lib/http-proxy/passes/web-outgoing.js index 9281c4a45..52e6c828e 100644 --- a/lib/http-proxy/passes/web-outgoing.js +++ b/lib/http-proxy/passes/web-outgoing.js @@ -1,5 +1,6 @@ -var passes = exports; - +var url = require('url') +var passes = exports; +var redirectRegex = /^30(1|2|7|8)$/; /*! * Array of passes. * @@ -43,6 +44,13 @@ var passes = exports; } }, + function setRedirectHostRewrite(req, res, proxyRes, options) { + if (options.hostRewrite && redirectRegex.test(proxyRes.statusCode)) { + var u = url.parse(proxyRes.headers['location']); + u.host = options.hostRewrite; + proxyRes.headers['location'] = u.format(); + } + }, /** * Copy headers from proxyResponse to response * set each header in response object. diff --git a/test/lib-http-proxy-passes-web-outgoing-test.js b/test/lib-http-proxy-passes-web-outgoing-test.js index 0ae0bda6f..ee1077e03 100644 --- a/test/lib-http-proxy-passes-web-outgoing-test.js +++ b/test/lib-http-proxy-passes-web-outgoing-test.js @@ -2,6 +2,58 @@ var httpProxy = require('../lib/http-proxy/passes/web-outgoing'), expect = require('expect.js'); describe('lib/http-proxy/passes/web-outgoing.js', function () { + describe('#setRedirectHostRewrite', function () { + context('rewrites location host to option', function() { + beforeEach(function() { + this.proxyRes = { + statusCode: 301, + headers: { + location: "http://f.com/" + } + }; + + this.options = { + hostRewrite: "x.com" + }; + }); + + it('on 301', function() { + this.proxyRes.statusCode = 301; + httpProxy.setRedirectHostRewrite({}, {}, this.proxyRes, this.options); + expect(this.proxyRes.headers.location).to.eql('http://'+this.options.hostRewrite+'/'); + }); + + it('on 302', function() { + this.proxyRes.statusCode = 302; + httpProxy.setRedirectHostRewrite({}, {}, this.proxyRes, this.options); + expect(this.proxyRes.headers.location).to.eql('http://'+this.options.hostRewrite+'/'); + }); + + it('on 307', function() { + this.proxyRes.statusCode = 307; + httpProxy.setRedirectHostRewrite({}, {}, this.proxyRes, this.options); + expect(this.proxyRes.headers.location).to.eql('http://'+this.options.hostRewrite+'/'); + }); + + it('on 308', function() { + this.proxyRes.statusCode = 308; + httpProxy.setRedirectHostRewrite({}, {}, this.proxyRes, this.options); + expect(this.proxyRes.headers.location).to.eql('http://'+this.options.hostRewrite+'/'); + }); + + it('not on 200', function() { + this.proxyRes.statusCode = 200; + httpProxy.setRedirectHostRewrite({}, {}, this.proxyRes, this.options); + expect(this.proxyRes.headers.location).to.eql('http://f.com/'); + }); + + it('not when hostRewrite is unset', function() { + httpProxy.setRedirectHostRewrite({}, {}, this.proxyRes, {}); + expect(this.proxyRes.headers.location).to.eql('http://f.com/'); + }); + }); + }); + describe('#setConnection', function () { it('set the right connection with 1.0 - `close`', function() { var proxyRes = { headers: {} };