From a5e416e3a2f8dd34ce5051c752c1b2bc4b982393 Mon Sep 17 00:00:00 2001 From: Stefano Borini Date: Tue, 6 Sep 2016 17:28:18 +0100 Subject: [PATCH 1/3] Added options for rewriting Location headers --- bin/configurable-http-proxy | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bin/configurable-http-proxy b/bin/configurable-http-proxy index d6870285..22bc6e4e 100755 --- a/bin/configurable-http-proxy +++ b/bin/configurable-http-proxy @@ -42,6 +42,8 @@ args .option('--no-x-forward', "Don't add 'X-forward-' headers to proxied requests") .option('--no-prepend-path', "Avoid prepending target paths to proxied requests") .option('--no-include-prefix', "Don't include the routing prefix in proxied requests") + .option('--auto-rewrite', "Rewrite the Location header host/port in redirect responses") + .option('--protocol-rewrite ', "Rewrite the Location header protocol in redirect responses to the specified protocol") .option('--insecure', "Disable SSL cert verification") .option('--host-routing', "Use host routing (host as first level of path)") .option('--statsd-host ', 'Host to send statsd statistics to') @@ -181,6 +183,15 @@ if (args.insecure) options.secure = false; options.xfwd = args.xForward ? false : true; options.prependPath = args.prependPath; options.includePrefix = args.includePrefix; +if (args.autoRewrite) { + options.autoRewrite = true; + log.info("AutoRewrite of Location headers enabled."); +} + +if (args.protocolRewrite) { + options.protocolRewrite = args.protocolRewrite; + log.info("ProtocolRewrite enabled. Rewriting to "+options.protocolRewrite); +} if (!options.auth_token) { log.warn("REST API is not authenticated."); From c683b4cc672760dad8629d60a1be0b4753f7602f Mon Sep 17 00:00:00 2001 From: Stefano Borini Date: Wed, 7 Sep 2016 13:26:30 +0100 Subject: [PATCH 2/3] Added tests --- lib/testutil.js | 19 +++++++++++++++++++ test/proxy_spec.js | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/lib/testutil.js b/lib/testutil.js index f93a6a4b..5faa8b1c 100644 --- a/lib/testutil.js +++ b/lib/testutil.js @@ -44,6 +44,25 @@ var add_target = exports.add_target = function (proxy, path, port, websocket, ta proxy.add_route(path, {target: target}); }; +var add_target_redirecting = exports.add_target_redirecting = function (proxy, path, port, target_path, redirect_to) { + // Like the above, but the server returns a redirect response with a Location header. + // Cannot use default arguments as they are apparently not supported. + var target = 'http://127.0.0.1:' + port; + if (target_path) { + target = target + target_path; + } + var server; + server = http.createServer(function (req, res) { + res.setHeader("Location", redirect_to); + res.statusCode = 301; + res.write(''); + res.end(); + }); + server.listen(port); + servers.push(server); + proxy.add_route(path, {target: target}); +}; + exports.setup_proxy = function (port, callback, options, paths) { options = options || {}; options.auth_token = 'secret'; diff --git a/test/proxy_spec.js b/test/proxy_spec.js index b745c8ce..103fbd5f 100644 --- a/test/proxy_spec.js +++ b/test/proxy_spec.js @@ -18,6 +18,7 @@ describe("Proxy Tests", function () { var r = request.defaults({ method: 'GET', url: proxy_url, + followRedirect: false, }); beforeEach(function (callback) { @@ -258,4 +259,42 @@ describe("Proxy Tests", function () { }); }); }); + + it("Redirect location untouched without rewrite options", function (done) { + var redirect_to = 'http://foo.com:12345/whatever'; + util.add_target_redirecting(proxy, '/external/urlpath/', test_port, '/internal/urlpath/', redirect_to); + r(proxy_url + '/external/urlpath/rest/of/it', function (error, res, body) { + expect(error).toBe(null); + expect(res.statusCode).toEqual(301); + expect(res.headers["location"]).toEqual(redirect_to); + done(); + }); + }); + + it("Redirect location with rewriting", function (done) { + var proxy_port = 55555; + var options = { + protocolRewrite: "https", + autoRewrite: true, + }; + + // where the backend server redirects us. + // Note that http-proxy requires (logically) the redirection to be to the same (internal) host. + var redirect_to = "http://127.0.0.1:"+test_port+"/whatever"; + + var validation_callback = function (proxy) { + util.add_target_redirecting(proxy, '/external/urlpath/', test_port, '/internal/urlpath/', redirect_to); + var url = 'http://127.0.0.1:' + proxy_port; + + r(url + '/external/urlpath/', function (error, res, body) { + expect(error).toBe(null); + expect(res.statusCode).toEqual(301); + expect(res.headers["location"]).toEqual("https://127.0.0.1:"+proxy_port+"/whatever"); + done(); + }); + }; + + var proxy = util.setup_proxy(proxy_port, validation_callback, options, []); + }); + }); From 4484d76a7816a238f8298e4b2872233ca336906e Mon Sep 17 00:00:00 2001 From: Stefano Borini Date: Wed, 7 Sep 2016 13:44:58 +0100 Subject: [PATCH 3/3] Silencing stupid request from jslinter. --- test/proxy_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/proxy_spec.js b/test/proxy_spec.js index 103fbd5f..3b2b0a8a 100644 --- a/test/proxy_spec.js +++ b/test/proxy_spec.js @@ -266,7 +266,7 @@ describe("Proxy Tests", function () { r(proxy_url + '/external/urlpath/rest/of/it', function (error, res, body) { expect(error).toBe(null); expect(res.statusCode).toEqual(301); - expect(res.headers["location"]).toEqual(redirect_to); + expect(res.headers.location).toEqual(redirect_to); done(); }); }); @@ -289,7 +289,7 @@ describe("Proxy Tests", function () { r(url + '/external/urlpath/', function (error, res, body) { expect(error).toBe(null); expect(res.statusCode).toEqual(301); - expect(res.headers["location"]).toEqual("https://127.0.0.1:"+proxy_port+"/whatever"); + expect(res.headers.location).toEqual("https://127.0.0.1:"+proxy_port+"/whatever"); done(); }); };