Make gate keeper to save relative location header path
Why we need this: Some middlewares want to keep HTTP Location header as relative path (e.g. using Load balancer in front of proxy). What is the problem in current Swift: Current Swift already has the flag to keep it as relative when returning the reponse using swift.common.swob.Response. However, auth_token middleware, that is from keystonemiddleware, unfortunately can change the relative path to absolute because of using webob instead of swob. What this patch is doing: Make gate_keeper able to re-transform the location header from absolute path to relative path if 'swift.leave_relative_location' is explicitely set because gate_keeper should be the most left side middleware except catch_errors middleware in the pipeline. Change-Id: Ic634c3f1b1e26635206d5a54df8b15354e8df163
This commit is contained in:
parent
d2e32b39e8
commit
d6fcf74594
@ -36,6 +36,7 @@ from swift.common.utils import get_logger, config_true_value
|
||||
from swift.common.request_helpers import (
|
||||
remove_items, get_sys_meta_prefix, OBJECT_TRANSIENT_SYSMETA_PREFIX
|
||||
)
|
||||
from six.moves.urllib.parse import urlsplit
|
||||
import re
|
||||
|
||||
#: A list of python regular expressions that will be used to
|
||||
@ -89,9 +90,29 @@ class GatekeeperMiddleware(object):
|
||||
[('X-Timestamp', ts)])
|
||||
|
||||
def gatekeeper_response(status, response_headers, exc_info=None):
|
||||
def fixed_response_headers():
|
||||
def relative_path(value):
|
||||
parsed = urlsplit(v)
|
||||
new_path = parsed.path
|
||||
if parsed.query:
|
||||
new_path += ('?%s' % parsed.query)
|
||||
if parsed.fragment:
|
||||
new_path += ('#%s' % parsed.fragment)
|
||||
return new_path
|
||||
|
||||
if not env.get('swift.leave_relative_location'):
|
||||
return response_headers
|
||||
else:
|
||||
return [
|
||||
(k, v) if k.lower() != 'location' else
|
||||
(k, relative_path(v)) for (k, v) in response_headers
|
||||
]
|
||||
|
||||
response_headers = fixed_response_headers()
|
||||
removed = filter(
|
||||
lambda h: self.outbound_condition(h[0]),
|
||||
response_headers)
|
||||
|
||||
if removed:
|
||||
self.logger.debug('removed response headers: %s' % removed)
|
||||
new_headers = filter(
|
||||
|
@ -215,5 +215,36 @@ class TestGatekeeper(unittest.TestCase):
|
||||
for app_hdrs in ({}, self.forbidden_headers_out):
|
||||
self._test_duplicate_headers_not_removed(method, app_hdrs)
|
||||
|
||||
def _test_location_header(self, location_path):
|
||||
headers = {'Location': location_path}
|
||||
req = Request.blank(
|
||||
'/v/a/c', environ={'REQUEST_METHOD': 'GET',
|
||||
'swift.leave_relative_location': True})
|
||||
|
||||
class SelfishApp(FakeApp):
|
||||
def __call__(self, env, start_response):
|
||||
self.req = Request(env)
|
||||
resp = Response(request=self.req, body='FAKE APP',
|
||||
headers=self.headers)
|
||||
# like webob, middlewares in the pipeline may rewrite
|
||||
# location header from relative to absolute
|
||||
resp.location = resp.absolute_location()
|
||||
return resp(env, start_response)
|
||||
|
||||
selfish_app = SelfishApp(headers=headers)
|
||||
|
||||
app = self.get_app(selfish_app, {})
|
||||
resp = req.get_response(app)
|
||||
self.assertEqual('200 OK', resp.status)
|
||||
self.assertIn('Location', resp.headers)
|
||||
self.assertEqual(resp.headers['Location'], location_path)
|
||||
|
||||
def test_location_header_fixed(self):
|
||||
self._test_location_header('/v/a/c/o2')
|
||||
self._test_location_header('/v/a/c/o2?query=path&query2=doit')
|
||||
self._test_location_header('/v/a/c/o2?query=path#test')
|
||||
self._test_location_header('/v/a/c/o2;whatisparam?query=path#test')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user