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 (
|
from swift.common.request_helpers import (
|
||||||
remove_items, get_sys_meta_prefix, OBJECT_TRANSIENT_SYSMETA_PREFIX
|
remove_items, get_sys_meta_prefix, OBJECT_TRANSIENT_SYSMETA_PREFIX
|
||||||
)
|
)
|
||||||
|
from six.moves.urllib.parse import urlsplit
|
||||||
import re
|
import re
|
||||||
|
|
||||||
#: A list of python regular expressions that will be used to
|
#: A list of python regular expressions that will be used to
|
||||||
@ -89,9 +90,29 @@ class GatekeeperMiddleware(object):
|
|||||||
[('X-Timestamp', ts)])
|
[('X-Timestamp', ts)])
|
||||||
|
|
||||||
def gatekeeper_response(status, response_headers, exc_info=None):
|
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(
|
removed = filter(
|
||||||
lambda h: self.outbound_condition(h[0]),
|
lambda h: self.outbound_condition(h[0]),
|
||||||
response_headers)
|
response_headers)
|
||||||
|
|
||||||
if removed:
|
if removed:
|
||||||
self.logger.debug('removed response headers: %s' % removed)
|
self.logger.debug('removed response headers: %s' % removed)
|
||||||
new_headers = filter(
|
new_headers = filter(
|
||||||
|
@ -215,5 +215,36 @@ class TestGatekeeper(unittest.TestCase):
|
|||||||
for app_hdrs in ({}, self.forbidden_headers_out):
|
for app_hdrs in ({}, self.forbidden_headers_out):
|
||||||
self._test_duplicate_headers_not_removed(method, app_hdrs)
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user