From 6db12b87ff6055f1b4d647a440e68a93387f4b24 Mon Sep 17 00:00:00 2001 From: Romain LE DISEZ Date: Sat, 18 Feb 2017 16:22:11 +0100 Subject: [PATCH] Fix domain_remap when obj starts/ends with slash domain_remap strip all starting/ending slashes. This behavior does not allow to access objects starting or ending with slash. It is also impacting staticweb middleware as staticweb tries to redirect pseudo-directory to an URL with an ending slash, but as domain_remap strip it, it goes to an infinite loop. With this commit, the path of the request is passed as-is when reconstructing the new request path. Example http://www.example.com//obj/ was previously rewritten to http://storage.example.com/v1/AUTH_abc/container/obj. It is now rewritten to http://storage.example.com/v1/AUTH_abc/container//obj/ Closes-Bug: #1682293 Co-Authored-By: Christian Schwede Change-Id: I1ef6b8752183d27103a3b0e720edcb4ce06fb837 --- swift/common/middleware/domain_remap.py | 13 +++---- .../common/middleware/test_domain_remap.py | 34 +++++++++++++++---- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/swift/common/middleware/domain_remap.py b/swift/common/middleware/domain_remap.py index 60f3d475a2..23bd72ffaa 100644 --- a/swift/common/middleware/domain_remap.py +++ b/swift/common/middleware/domain_remap.py @@ -73,7 +73,7 @@ class DomainRemapMiddleware(object): if not s.startswith('.')] self.storage_domain += [s for s in list_from_csv(storage_domain) if s.startswith('.')] - self.path_root = conf.get('path_root', 'v1').strip('/') + self.path_root = '/' + conf.get('path_root', 'v1').strip('/') prefixes = conf.get('reseller_prefixes', 'AUTH') self.reseller_prefixes = list_from_csv(prefixes) self.reseller_prefixes_lower = [x.lower() @@ -124,14 +124,15 @@ class DomainRemapMiddleware(object): # account prefix is not in config list. bail. return self.app(env, start_response) - path = env['PATH_INFO'].strip('/') - new_path_parts = ['', self.path_root, account] + path = env['PATH_INFO'] + new_path_parts = [self.path_root, account] if container: new_path_parts.append(container) if path.startswith(self.path_root): - path = path[len(self.path_root):].lstrip('/') - if path: - new_path_parts.append(path) + path = path[len(self.path_root):] + if path.startswith('/'): + path = path[1:] + new_path_parts.append(path) new_path = '/'.join(new_path_parts) env['PATH_INFO'] = new_path return self.app(env, start_response) diff --git a/test/unit/common/middleware/test_domain_remap.py b/test/unit/common/middleware/test_domain_remap.py index 48b9cec08b..4013a1a1f1 100644 --- a/test/unit/common/middleware/test_domain_remap.py +++ b/test/unit/common/middleware/test_domain_remap.py @@ -55,21 +55,21 @@ class TestDomainRemap(unittest.TestCase): 'SERVER_NAME': 'AUTH_a.example.com'}, headers={'Host': None}) resp = self.app(req.environ, start_response) - self.assertEqual(resp, '/v1/AUTH_a') + self.assertEqual(resp, '/v1/AUTH_a/') req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'}, headers={'Host': 'AUTH_a.example.com'}) resp = self.app(req.environ, start_response) - self.assertEqual(resp, '/v1/AUTH_a') + self.assertEqual(resp, '/v1/AUTH_a/') req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'}, headers={'Host': 'AUTH-uuid.example.com'}) resp = self.app(req.environ, start_response) - self.assertEqual(resp, '/v1/AUTH_uuid') + self.assertEqual(resp, '/v1/AUTH_uuid/') def test_domain_remap_account_container(self): req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'}, headers={'Host': 'c.AUTH_a.example.com'}) resp = self.app(req.environ, start_response) - self.assertEqual(resp, '/v1/AUTH_a/c') + self.assertEqual(resp, '/v1/AUTH_a/c/') def test_domain_remap_extra_subdomains(self): req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'}, @@ -81,13 +81,35 @@ class TestDomainRemap(unittest.TestCase): req = Request.blank('/v1', environ={'REQUEST_METHOD': 'GET'}, headers={'Host': 'AUTH_a.example.com'}) resp = self.app(req.environ, start_response) - self.assertEqual(resp, '/v1/AUTH_a') + self.assertEqual(resp, '/v1/AUTH_a/') def test_domain_remap_account_container_with_path_root(self): req = Request.blank('/v1', environ={'REQUEST_METHOD': 'GET'}, headers={'Host': 'c.AUTH_a.example.com'}) resp = self.app(req.environ, start_response) - self.assertEqual(resp, '/v1/AUTH_a/c') + self.assertEqual(resp, '/v1/AUTH_a/c/') + + def test_domain_remap_account_container_with_path_obj_slash_v1(self): + # Include http://localhost because urlparse used in Request.__init__ + # parse //v1 as http://v1 + req = Request.blank('http://localhost//v1', + environ={'REQUEST_METHOD': 'GET'}, + headers={'Host': 'c.AUTH_a.example.com'}) + resp = self.app(req.environ, start_response) + self.assertEqual(resp, '/v1/AUTH_a/c//v1') + + def test_domain_remap_account_container_with_root_path_obj_slash_v1(self): + req = Request.blank('/v1//v1', + environ={'REQUEST_METHOD': 'GET'}, + headers={'Host': 'c.AUTH_a.example.com'}) + resp = self.app(req.environ, start_response) + self.assertEqual(resp, '/v1/AUTH_a/c//v1') + + def test_domain_remap_account_container_with_path_trailing_slash(self): + req = Request.blank('/obj/', environ={'REQUEST_METHOD': 'GET'}, + headers={'Host': 'c.AUTH_a.example.com'}) + resp = self.app(req.environ, start_response) + self.assertEqual(resp, '/v1/AUTH_a/c/obj/') def test_domain_remap_account_container_with_path(self): req = Request.blank('/obj', environ={'REQUEST_METHOD': 'GET'},