From a46dfbfb7b9e05db2d5d02d1c745aa6bdacdc14b Mon Sep 17 00:00:00 2001 From: Anastasia Kuznetsova Date: Thu, 23 Mar 2017 17:15:59 +0400 Subject: [PATCH] Change Http action result content encoding Sometimes action result is present not in "utf-8", it cases to "UnicodeDecodeError: 'utf8' codec can't decode byte" so need to pass proper encoding format in serialiser and deserialiser if it is different from default, but it should be resolved in general as a fix for another bug (#1676411). As a hotfix for linked bug, encoding was changed in the run Http action method directly. Also default encoding value in the FakeHTTPResponse was changed from 'utf8' to 'utf-8' like in official python request lib docs. Change-Id: I0ab9ec84c0973f362b57ab82248f27768a984678 Closes-Bug: #1667415 --- mistral/actions/std_actions.py | 9 ++++++++- mistral/tests/unit/base.py | 6 +++--- .../tests/api/v2/test_action_executions.py | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/mistral/actions/std_actions.py b/mistral/actions/std_actions.py index 968ad13d..3bd56490 100644 --- a/mistral/actions/std_actions.py +++ b/mistral/actions/std_actions.py @@ -196,12 +196,19 @@ class HTTPAction(base.Action): "HTTP action response:\n%s\n%s" % (resp.status_code, resp.content) ) + # TODO(akuznetsova): Need to refactor Mistral serialiser and + # deserializer to have an ability to pass needed encoding and work + # with it. Now it can process only default 'utf-8' encoding. + # Appropriate bug #1676411 was created. + # Represent important resp data as a dictionary. try: - content = resp.json() + content = resp.json(encoding=resp.encoding) except Exception as e: LOG.debug("HTTP action response is not json.") content = resp.content + if resp.encoding != 'utf-8': + content = content.decode(resp.encoding).encode('utf-8') _result = { 'content': content, diff --git a/mistral/tests/unit/base.py b/mistral/tests/unit/base.py index 12a84782..0d2d8a70 100644 --- a/mistral/tests/unit/base.py +++ b/mistral/tests/unit/base.py @@ -81,7 +81,7 @@ def register_action_class(name, cls, attributes=None, desc=None): class FakeHTTPResponse(object): def __init__(self, text, status_code, reason=None, headers=None, - history=None, encoding='utf8', url='', cookies=None, + history=None, encoding='utf-8', url='', cookies=None, elapsed=None): self.text = text self.content = text @@ -94,8 +94,8 @@ class FakeHTTPResponse(object): self.cookies = cookies or {} self.elapsed = elapsed or datetime.timedelta(milliseconds=123) - def json(self): - return json.loads(self.text) + def json(self, **kwargs): + return json.loads(self.text, **kwargs) class BaseTest(base.BaseTestCase): diff --git a/mistral_tempest_tests/tests/api/v2/test_action_executions.py b/mistral_tempest_tests/tests/api/v2/test_action_executions.py index 143461dc..7a4467e6 100644 --- a/mistral_tempest_tests/tests/api/v2/test_action_executions.py +++ b/mistral_tempest_tests/tests/api/v2/test_action_executions.py @@ -155,6 +155,22 @@ class ActionExecutionTestsV2(base.TestCase): output = json.loads(body['output']) self.assertEqual(404, output['result']['status']) + @test.attr(type='sanity') + @test.related_bug('1667415') + @decorators.idempotent_id('3c73de7a-4af0-4657-90d6-d7ebd3c7da18') + def test_run_action_std_http_non_utf8_response(self): + resp, body = self.client.create_action_execution( + { + 'name': 'std.http', + 'input': + '{"url": "https://www.google.co.il/search?q=testTest"}' + } + ) + + self.assertEqual(201, resp.status) + output = json.loads(body['output']) + self.assertEqual(200, output['result']['status']) + @test.attr(type='sanity') @decorators.idempotent_id('d98586bf-fdc4-44f6-9837-700d35b5f889') def test_create_action_execution(self):