From 708d1bccec95308e19fadeacb8fd5de4ef7e1255 Mon Sep 17 00:00:00 2001 From: Oliver Bruns Date: Mon, 9 Feb 2015 21:47:52 +0100 Subject: [PATCH 1/3] replace direct member access with method call --- src/HttpLibrary/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/HttpLibrary/__init__.py b/src/HttpLibrary/__init__.py index ae11328..6ee29b5 100644 --- a/src/HttpLibrary/__init__.py +++ b/src/HttpLibrary/__init__.py @@ -483,11 +483,11 @@ def response_body_should_contain(self, should_contain): | Response Body Should Contain | encoding="UTF-8" | """ logger.debug('Testing whether "%s" contains "%s".' % ( - self.response.body, should_contain)) + self.get_response_body(), should_contain)) - assert should_contain in self.response.body, \ + assert should_contain in self.get_response_body(), \ '"%s" should have contained "%s", but did not.' % ( - self.response.body, should_contain) + self.get_response_body(), should_contain) def log_response_body(self, log_level='INFO'): """ @@ -495,9 +495,9 @@ def log_response_body(self, log_level='INFO'): Specify `log_level` (default: "INFO") to set the log level. """ - if self.response.body: + if self.get_response_body(): logger.write("Response body:", log_level) - logger.write(self.response.body, log_level) + logger.write(self.get_response_body(), log_level) else: logger.debug("No response body received", log_level) From f4cc5b7acca64c1ba7fa4641ce8c3ed98440010f Mon Sep 17 00:00:00 2001 From: Oliver Bruns Date: Mon, 9 Feb 2015 21:28:12 +0100 Subject: [PATCH 2/3] return the response body as a unicode object Keep the symmetry with set_request_body() which encodes the unicode object (Robot Framework defaults to unicode for all strings) into an instance of str by decoding the response into an instance of unicode in get_response_body(). Failure to do so causes UnicodeDecodeErrors in all keywords that compare the response body against a given string if any of the two contains Unicode characters. --- src/HttpLibrary/__init__.py | 2 +- tests/http/simple.txt | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/HttpLibrary/__init__.py b/src/HttpLibrary/__init__.py index 6ee29b5..6b8bbb3 100644 --- a/src/HttpLibrary/__init__.py +++ b/src/HttpLibrary/__init__.py @@ -471,7 +471,7 @@ def get_response_body(self): | ${body}= | Get Response Body | | | Should Start With | ${body} | Date: Mon, 9 Feb 2015 21:25:52 +0100 Subject: [PATCH 3/3] convert HTTP header keys from unicode objects into str objects Robot Framework defaults to unicode objects for all strings created. As a result, httplib.py:848 has unicode += str (msg += message_body) which crashes with UnicodeDecodeError when the body contains Unicode characters: File "/usr/lib64/python2.7/httplib.py", line 1001, in request self._send_request(method, url, body, headers) File "/usr/lib64/python2.7/httplib.py", line 1035, in _send_request self.endheaders(body) File "/usr/lib64/python2.7/httplib.py", line 997, in endheaders self._send_output(message_body) File "/usr/lib64/python2.7/httplib.py", line 848, in _send_output msg += message_body UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 32: ordinal not in range(128) A similar stack trace has been posted as part of Python bug #11898 [1] (duplicated by #12398 [2]) which has later been closed as a programming error. Both robotframework-httplibrary and webtest treat the 'Content-Type' header special which results in surprising behavior regarding the tests: Had the 'Accept' header been removed from the provided test case no UnicodeDecodeError would have been thrown in httplib.py:848. Turning unicode objects into str objects is the right thing to do according to the HTTP standard ([3], updated by [5]) because it requires conformity to MIME [5] (hint by [6]). [1] http://bugs.python.org/issue11898 [2] http://bugs.python.org/issue12398 [3] https://tools.ietf.org/html/rfc2616 [4] https://tools.ietf.org/html/rfc2047 [5] https://tools.ietf.org/html/rfc7230 [6] https://stackoverflow.com/a/5426648 --- src/HttpLibrary/__init__.py | 2 +- tests/http/simple.txt | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/HttpLibrary/__init__.py b/src/HttpLibrary/__init__.py index 6b8bbb3..8e860b8 100644 --- a/src/HttpLibrary/__init__.py +++ b/src/HttpLibrary/__init__.py @@ -431,7 +431,7 @@ def set_request_header(self, header_name, header_value): """ logger.info( 'Set request header "%s" to "%s"' % (header_name, header_value)) - self.context.request_headers[header_name] = header_value + self.context.request_headers[str(header_name)] = header_value def set_basic_auth(self, username, password): """ diff --git a/tests/http/simple.txt b/tests/http/simple.txt index 092fd54..fd08760 100644 --- a/tests/http/simple.txt +++ b/tests/http/simple.txt @@ -176,6 +176,15 @@ POST with Unicode request body POST /echo Response Body Should Contain Tschüss Süße +POST with Unicode request body and Accept Header + [Documentation] Request body and headers must allow to be concatenated + [Tags] unicode + Set Request Body Tschüss Süße + Set Request Header Accept application/json + Set Request Header Content-Type text/plain + POST /echo + Response Body Should Contain Tschüss Süße + PUT with two word request body Set Request Body Tooot Tooooot Set Request Header Content-Type text/plain