From 4a6f3e9a48ecd893d228b69f7616828b727b287d Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Mon, 29 Jan 2018 12:38:34 +0100 Subject: [PATCH] Handle URL reconstruction in PEP333 compatible fashion The Pecan url in wsgi forward scenarios is not correct, as it does not handle the extra headers injected by the forwarding handler. Improve this to properly detect the https case in case the loadbalancer terminates SSL as well and always return the original's request HOST for consistency. Change-Id: I3a208abbc6134d1c7be245d35eb4564ef886bd9b --- barbican/common/utils.py | 11 +++++++++-- barbican/tests/utils.py | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/barbican/common/utils.py b/barbican/common/utils.py index 030d113e1..09f923783 100644 --- a/barbican/common/utils.py +++ b/barbican/common/utils.py @@ -78,10 +78,17 @@ def get_base_url_from_request(): """ if not CONF.host_href and hasattr(pecan.request, 'url'): p_url = parse.urlsplit(pecan.request.url) + # Pecan does not handle X_FORWARDED_PROTO yet, so we need to + # handle it ourselves. see lp#1445290 + scheme = pecan.request.environ.get('HTTP_X_FORWARDED_PROTO', 'http') + # Pecan does not handle url reconstruction according to + # https://www.python.org/dev/peps/pep-0333/#url-reconstruction + netloc = pecan.request.environ.get('HTTP_HOST', p_url.netloc) + # FIXME: implement SERVER_NAME lookup if HTTP_HOST is not set if p_url.path: - base_url = '%s://%s%s' % (p_url.scheme, p_url.netloc, p_url.path) + base_url = '%s://%s%s' % (scheme, netloc, p_url.path) else: - base_url = '%s://%s' % (p_url.scheme, p_url.netloc) + base_url = '%s://%s' % (scheme, netloc) return base_url else: # when host_href is set or flow is not within wsgi request context return CONF.host_href diff --git a/barbican/tests/utils.py b/barbican/tests/utils.py index 893b817e8..ccd3d355f 100644 --- a/barbican/tests/utils.py +++ b/barbican/tests/utils.py @@ -49,6 +49,7 @@ def mock_pecan_request(test_instance, host=None): mock_req = patcher_obj.start() test_instance.addCleanup(patcher_obj.stop) mock_req.url = host + mock_req.environ = os.environ.copy() @contextmanager