From aa2f1db1b71c1b2bf746b72515e3efd15598b6aa Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Tue, 11 Jun 2019 14:50:49 -0700 Subject: [PATCH] Ensure get_*_info keys are native strings Change-Id: I29bbea48ae38cfabf449a9f4cca1f5f27769405a --- swift/proxy/controllers/base.py | 16 ++++++++++++++-- test/unit/proxy/controllers/test_base.py | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/swift/proxy/controllers/base.py b/swift/proxy/controllers/base.py index 06328def36..568c6ddb49 100644 --- a/swift/proxy/controllers/base.py +++ b/swift/proxy/controllers/base.py @@ -594,13 +594,25 @@ def _get_info_from_memcache(app, env, account, container=None): info = memcache.get(cache_key) if info and six.PY2: # Get back to native strings + new_info = {} for key in info: + new_key = key.encode("utf-8") if isinstance( + key, six.text_type) else key if isinstance(info[key], six.text_type): - info[key] = info[key].encode("utf-8") + new_info[new_key] = info[key].encode("utf-8") elif isinstance(info[key], dict): + new_info[new_key] = {} for subkey, value in info[key].items(): + new_subkey = subkey.encode("utf-8") if isinstance( + subkey, six.text_type) else subkey if isinstance(value, six.text_type): - info[key][subkey] = value.encode("utf-8") + new_info[new_key][new_subkey] = \ + value.encode("utf-8") + else: + new_info[new_key][new_subkey] = value + else: + new_info[new_key] = info[key] + info = new_info if info: env.setdefault('swift.infocache', {})[cache_key] = info return info diff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py index a1a54c6729..2298dc466a 100644 --- a/test/unit/proxy/controllers/test_base.py +++ b/test/unit/proxy/controllers/test_base.py @@ -168,7 +168,8 @@ class FakeCache(FakeMemcache): super(FakeCache, self).__init__() if pre_cached: self.store.update(pre_cached) - self.stub = stub + # Fake a json roundtrip + self.stub = json.loads(json.dumps(stub)) def get(self, key): return self.stub or self.store.get(key) @@ -370,18 +371,27 @@ class TestFuncs(unittest.TestCase): def test_get_container_info_cache(self): cache_stub = { 'status': 404, 'bytes': 3333, 'object_count': 10, - 'versions': u"\u1F4A9"} + 'versions': u"\U0001F4A9", + 'meta': {u'some-\N{SNOWMAN}': u'non-ascii meta \U0001F334'}} req = Request.blank("/v1/account/cont", environ={'swift.cache': FakeCache(cache_stub)}) resp = get_container_info(req.environ, FakeApp()) + self.assertEqual([(k, type(k)) for k in resp], + [(k, str) for k in resp]) self.assertEqual(resp['storage_policy'], 0) self.assertEqual(resp['bytes'], 3333) self.assertEqual(resp['object_count'], 10) self.assertEqual(resp['status'], 404) if six.PY3: - self.assertEqual(resp['versions'], u'\u1f4a9') + self.assertEqual(resp['versions'], u'\U0001f4a9') else: - self.assertEqual(resp['versions'], "\xe1\xbd\x8a\x39") + self.assertEqual(resp['versions'], "\xf0\x9f\x92\xa9") + for subdict in resp.values(): + if isinstance(subdict, dict): + self.assertEqual([(k, type(k), v, type(v)) + for k, v in subdict.items()], + [(k, str, v, str) + for k, v in subdict.items()]) def test_get_container_info_env(self): cache_key = get_cache_key("account", "cont")