From 64cf9d064b7d5ec8d75e57b94a869187fbbaf127 Mon Sep 17 00:00:00 2001 From: Duc Truong Date: Mon, 10 Dec 2018 23:47:14 +0000 Subject: [PATCH] Convert requests response from byte to string In python 3 byte objects are no longer treated as strings. Requests responses can potentially be of type byte. In that case the response needs to be converted to string. Change-Id: Id6959c3e4383281202afb3652afbb5220c39e5e4 --- senlin/common/utils.py | 5 +++++ senlin/tests/unit/test_common_utils.py | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/senlin/common/utils.py b/senlin/common/utils.py index 56d5add16..b7ce36198 100644 --- a/senlin/common/utils.py +++ b/senlin/common/utils.py @@ -122,6 +122,11 @@ def url_fetch(url, timeout=1, allowed_schemes=('http', 'https'), verify=True): reader = resp.iter_content(chunk_size=1000) result = "" for chunk in reader: + if six.PY3 and isinstance(chunk, bytes): + # in python 2.7, bytes were implicitly converted to strings + # in python 3.5 this is no longer the case so we need this + # code to manually convert it + chunk = chunk.decode('utf-8') result += chunk if len(result) > cfg.CONF.max_response_size: raise URLFetchError("Data exceeds maximum allowed size (%s" diff --git a/senlin/tests/unit/test_common_utils.py b/senlin/tests/unit/test_common_utils.py index de962d724..3f6e6df82 100644 --- a/senlin/tests/unit/test_common_utils.py +++ b/senlin/tests/unit/test_common_utils.py @@ -122,6 +122,28 @@ class UrlFetchTest(base.SenlinTestCase): utils.url_fetch, url) self.assertIn("Data exceeds", six.text_type(exception)) + @mock.patch.object(requests, 'get') + def test_string_response(self, mock_get): + url = 'http://example.com/somedata' + data = '{ "foo": "bar" }' + + mock_resp = mock.Mock() + mock_resp.iter_content.return_value = [data] + mock_get.return_value = mock_resp + + self.assertEqual(data, utils.url_fetch(url)) + + @mock.patch.object(requests, 'get') + def test_byte_response(self, mock_get): + url = 'http://example.com/somedata' + data = b'{ "foo": "bar" }' + + mock_resp = mock.Mock() + mock_resp.iter_content.return_value = [data] + mock_get.return_value = mock_resp + + self.assertEqual('{ "foo": "bar" }', utils.url_fetch(url)) + class TestRandomName(base.SenlinTestCase):