diff --git a/gcloud/exceptions.py b/gcloud/exceptions.py index 78f641118031..07bad3e16496 100644 --- a/gcloud/exceptions.py +++ b/gcloud/exceptions.py @@ -171,6 +171,9 @@ def make_exception(response, content, use_json=True): :rtype: instance of :class:`GCloudError`, or a concrete subclass. :returns: Exception specific to the error response. """ + if not hasattr(content, 'keys') and not isinstance(content, str): + content = str(content.decode('utf-8')) + message = content errors = () diff --git a/gcloud/storage/connection.py b/gcloud/storage/connection.py index fabb1edfb94d..0fd057f2ec4c 100644 --- a/gcloud/storage/connection.py +++ b/gcloud/storage/connection.py @@ -235,6 +235,9 @@ def api_request(self, method, path, query_params=None, if not 200 <= response.status < 300: raise make_exception(response, content) + if not isinstance(content, str): + content = str(content.decode('utf-8')) + if content and expect_json: content_type = response.get('content-type', '') if not content_type.startswith('application/json'): diff --git a/gcloud/storage/test_connection.py b/gcloud/storage/test_connection.py index 1073f0969d18..8f21ebf21d63 100644 --- a/gcloud/storage/test_connection.py +++ b/gcloud/storage/test_connection.py @@ -206,6 +206,16 @@ def test_api_request_wo_json_expected(self): self.assertEqual(conn.api_request('GET', '/', expect_json=False), 'CONTENT') + def test_api_request_w_binary_json_string(self): + PROJECT = 'project' + conn = self._makeOne(PROJECT) + conn._http = Http( + {'status': '200', 'content-type': 'application/json'}, + b'{"foo": "bar"}' + ) + self.assertEqual(conn.api_request('GET', '/', expect_json=True), + {'foo': 'bar'}) + def test_api_request_w_query_params(self): from six.moves.urllib.parse import parse_qsl from six.moves.urllib.parse import urlsplit diff --git a/gcloud/test_exceptions.py b/gcloud/test_exceptions.py index ad7f89798660..0827bab51e68 100644 --- a/gcloud/test_exceptions.py +++ b/gcloud/test_exceptions.py @@ -61,6 +61,15 @@ def test_hit_w_content_as_str(self): self.assertEqual(exception.message, 'Not Found') self.assertEqual(list(exception.errors), []) + def test_hit_w_content_as_binary_string(self): + from gcloud.exceptions import BadRequest + response = _Response(400) + content = b'{"message": "Invalid argument."\n }\n' + exception = self._callFUT(response, content) + self.assertTrue(isinstance(exception, BadRequest)) + self.assertEqual(exception.message, 'Invalid argument.') + self.assertEqual(list(exception.errors), []) + def test_miss_w_content_as_dict(self): from gcloud.exceptions import GCloudError ERROR = {