From a8c2b46da624a2e133e5d6289529ba8ac63b2557 Mon Sep 17 00:00:00 2001 From: Walter Doekes Date: Thu, 20 May 2021 17:06:25 +0200 Subject: [PATCH] tempurl: Fix PUT upload to temp url on py3 Without this change, the self._response_headers gets a dict_items() type on PUT. But the rest of the code assumes that it is a list. Bug manifestation: File "swift/common/middleware/catch_errors.py", line 120, in handle_request self._response_headers.append(('X-Trans-Id', trans_id)) AttributeError: 'dict_items' object has no attribute 'append' Closes-Bug: #1929083 Change-Id: I5c398b6008716b64c668737e4201ba3b6ab3320b (cherry picked from commit 77530136f13f1fc0d8625d43e1689427d4ee2fad) --- swift/common/middleware/tempurl.py | 2 +- test/unit/common/middleware/test_tempurl.py | 36 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/swift/common/middleware/tempurl.py b/swift/common/middleware/tempurl.py index 524a03b057..1fcd5bcdd0 100644 --- a/swift/common/middleware/tempurl.py +++ b/swift/common/middleware/tempurl.py @@ -839,7 +839,7 @@ class TempURL(object): if h.startswith(p): del headers[h] break - return headers.items() + return list(headers.items()) def filter_factory(global_conf, **local_conf): diff --git a/test/unit/common/middleware/test_tempurl.py b/test/unit/common/middleware/test_tempurl.py index 6a08130c52..fe468cec72 100644 --- a/test/unit/common/middleware/test_tempurl.py +++ b/test/unit/common/middleware/test_tempurl.py @@ -476,6 +476,42 @@ class TestTempURL(unittest.TestCase): self.assertEqual(req.environ['swift.authorize_override'], True) self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl') + def test_put_response_headers_in_list(self): + class Validator(object): + def __init__(self, app): + self.app = app + self.status = None + self.headers = None + self.exc_info = None + + def start_response(self, status, headers, exc_info=None): + self.status = status + self.headers = headers + self.exc_info = exc_info + + def __call__(self, env, start_response): + resp_iter = self.app(env, self.start_response) + start_response(self.status, self.headers, self.exc_info) + return resp_iter + + method = 'PUT' + expires = int(time() + 86400) + path = '/v1/a/c/o' + key = b'abc' + hmac_body = ('%s\n%i\n%s' % (method, expires, path)).encode('utf-8') + sig = hmac.new(key, hmac_body, hashlib.sha1).hexdigest() + req = self._make_request( + path, keys=[key], + environ={'REQUEST_METHOD': 'PUT', + 'QUERY_STRING': 'temp_url_sig=%s&temp_url_expires=%s' % ( + sig, expires)}) + validator = Validator(self.tempurl) + resp = req.get_response(validator) + self.assertIsInstance(validator.headers, list) + self.assertEqual(resp.status_int, 404) + self.assertEqual(req.environ['swift.authorize_override'], True) + self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl') + def test_get_not_allowed_by_put(self): method = 'PUT' expires = int(time() + 86400)