diff --git a/swift/proxy/server.py b/swift/proxy/server.py index 05f207c872..a1de162fc8 100644 --- a/swift/proxy/server.py +++ b/swift/proxy/server.py @@ -300,11 +300,25 @@ class Controller(object): """Base WSGI controller class for the proxy""" server_type = _('Base') + # Ensure these are all lowercase + pass_through_headers = [] + def __init__(self, app): self.account_name = None self.app = app self.trans_id = '-' + def transfer_headers(self, src_headers, dst_headers): + x_remove = 'x-remove-%s-meta-' % self.server_type.lower() + x_meta = 'x-%s-meta-' % self.server_type.lower() + dst_headers.update((k.lower().replace('-remove', '', 1), '') + for k in src_headers + if k.lower().startswith(x_remove)) + dst_headers.update((k.lower(), v) + for k, v in src_headers.iteritems() + if k.lower() in self.pass_through_headers or + k.lower().startswith(x_meta)) + def error_increment(self, node): """ Handles incrementing error counts when talking to nodes. @@ -1503,9 +1517,7 @@ class ContainerController(Controller): 'X-Account-Partition': account_partition, 'X-Account-Device': account['device'], 'Connection': 'close'} - nheaders.update(value for value in req.headers.iteritems() - if value[0].lower() in self.pass_through_headers or - value[0].lower().startswith('x-container-meta-')) + self.transfer_headers(req.headers, nheaders) headers.append(nheaders) if self.app.memcache: cache_key = get_container_memcache_key(self.account_name, @@ -1530,9 +1542,7 @@ class ContainerController(Controller): headers = {'X-Timestamp': normalize_timestamp(time.time()), 'x-trans-id': self.trans_id, 'Connection': 'close'} - headers.update(value for value in req.headers.iteritems() - if value[0].lower() in self.pass_through_headers or - value[0].lower().startswith('x-container-meta-')) + self.transfer_headers(req.headers, headers) if self.app.memcache: cache_key = get_container_memcache_key(self.account_name, self.container_name) @@ -1620,8 +1630,7 @@ class AccountController(Controller): headers = {'X-Timestamp': normalize_timestamp(time.time()), 'x-trans-id': self.trans_id, 'Connection': 'close'} - headers.update(value for value in req.headers.iteritems() - if value[0].lower().startswith('x-account-meta-')) + self.transfer_headers(req.headers, headers) if self.app.memcache: self.app.memcache.delete('account%s' % req.path_info.rstrip('/')) return self.make_requests(req, self.app.account_ring, @@ -1638,8 +1647,7 @@ class AccountController(Controller): headers = {'X-Timestamp': normalize_timestamp(time.time()), 'X-Trans-Id': self.trans_id, 'Connection': 'close'} - headers.update(value for value in req.headers.iteritems() - if value[0].lower().startswith('x-account-meta-')) + self.transfer_headers(req.headers, headers) if self.app.memcache: self.app.memcache.delete('account%s' % req.path_info.rstrip('/')) resp = self.make_requests(req, self.app.account_ring, diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 6b1750b1ce..82cf9f144e 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -3372,19 +3372,26 @@ class TestContainerController(unittest.TestCase): def metadata_helper(self, method): for test_header, test_value in ( ('X-Container-Meta-TestHeader', 'TestValue'), - ('X-Container-Meta-TestHeader', '')): + ('X-Container-Meta-TestHeader', ''), + ('X-Remove-Container-Meta-TestHeader', 'anything')): test_errors = [] def test_connect(ipaddr, port, device, partition, method, path, headers=None, query_string=None): if path == '/a/c': + find_header = test_header + find_value = test_value + if find_header.lower().startswith('x-remove-'): + find_header = \ + find_header.lower().replace('-remove', '', 1) + find_value = '' for k, v in headers.iteritems(): - if k.lower() == test_header.lower() and \ - v == test_value: + if k.lower() == find_header.lower() and \ + v == find_value: break else: test_errors.append('%s: %s not in %s' % - (test_header, test_value, headers)) + (find_header, find_value, headers)) with save_globals(): controller = \ proxy_server.ContainerController(self.app, 'a', 'c') @@ -3788,19 +3795,26 @@ class TestAccountController(unittest.TestCase): def metadata_helper(self, method): for test_header, test_value in ( ('X-Account-Meta-TestHeader', 'TestValue'), - ('X-Account-Meta-TestHeader', '')): + ('X-Account-Meta-TestHeader', ''), + ('X-Remove-Account-Meta-TestHeader', 'anything')): test_errors = [] def test_connect(ipaddr, port, device, partition, method, path, headers=None, query_string=None): if path == '/a': + find_header = test_header + find_value = test_value + if find_header.lower().startswith('x-remove-'): + find_header = \ + find_header.lower().replace('-remove', '', 1) + find_value = '' for k, v in headers.iteritems(): - if k.lower() == test_header.lower() and \ - v == test_value: + if k.lower() == find_header.lower() and \ + v == find_value: break else: test_errors.append('%s: %s not in %s' % - (test_header, test_value, headers)) + (find_header, find_value, headers)) with save_globals(): self.app.allow_account_management = True controller = \