From 3e24926dd569bb450c4726f5ab1ffeaa4474d001 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Sat, 24 Feb 2018 15:33:02 +0800 Subject: [PATCH] fix #99: if charset is specified in content-type, request data should be encoded with charset encoding --- httprunner/__init__.py | 2 +- httprunner/client.py | 31 ++++++++++++++++++++++++++----- tests/test_client.py | 19 ++++++++++++++++--- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/httprunner/__init__.py b/httprunner/__init__.py index 53c505c6..17962017 100644 --- a/httprunner/__init__.py +++ b/httprunner/__init__.py @@ -1 +1 @@ -__version__ = '0.9.3b' \ No newline at end of file +__version__ = '0.9.3c' \ No newline at end of file diff --git a/httprunner/client.py b/httprunner/client.py index fb3161ac..5d150592 100644 --- a/httprunner/client.py +++ b/httprunner/client.py @@ -14,14 +14,34 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) absolute_http_url_regexp = re.compile(r"^https?://", re.I) +def get_charset_from_content_type(content_type): + """ extract charset encoding type from Content-Type + @param content_type + e.g. + application/json; charset=UTF-8 + application/x-www-form-urlencoded; charset=UTF-8 + @return: charset encoding type + UTF-8 + """ + content_type = content_type.lower() + if "charset=" not in content_type: + return None + + index = content_type.index("charset=") + len("charset=") + return content_type[index:] def prepare_kwargs(method, kwargs): if method == "POST": - # if request content-type is application/json, request data should be dumped - content_type = kwargs.get("headers", {}).get("content-type", "") - if content_type.startswith("application/json") and "data" in kwargs: - kwargs["data"] = json.dumps(kwargs["data"]) + content_type = kwargs.get("headers", {}).get("content-type") + if content_type and "data" in kwargs: + # if request content-type is application/json, request data should be dumped + if content_type.startswith("application/json"): + kwargs["data"] = json.dumps(kwargs["data"]) + # if charset is specified in content-type, request data should be encoded with charset encoding + charset = get_charset_from_content_type(content_type) + if charset: + kwargs["data"] = kwargs["data"].encode(charset) class ApiResponse(Response): @@ -100,7 +120,7 @@ class HttpSession(requests.Session): # prepend url with hostname unless it's already an absolute URL url = self._build_url(url) logger.log_info("{method} {url}".format(method=method, url=url)) - logger.log_debug("request kwargs: {kwargs}".format(kwargs=kwargs)) + logger.log_debug("request kwargs(raw): {kwargs}".format(kwargs=kwargs)) # store meta data that is used when reporting the request to locust's statistics request_meta = {} @@ -159,6 +179,7 @@ class HttpSession(requests.Session): """ try: prepare_kwargs(method, kwargs) + logger.log_debug("request kwargs(processed): {kwargs}".format(kwargs=kwargs)) return requests.Session.request(self, method, url, **kwargs) except (MissingSchema, InvalidSchema, InvalidURL): raise diff --git a/tests/test_client.py b/tests/test_client.py index 1c24557a..94cab9a3 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -36,7 +36,21 @@ class TestHttpClient(ApiServerUnittest): self.assertEqual(201, resp.status_code) self.assertEqual(True, resp.json()['success']) - def test_prepare_kwargs(self): + def test_prepare_kwargs_content_type_application_json_without_charset(self): + kwargs = { + "headers": { + "content-type": "application/json" + }, + "data": { + "a": 1, + "b": 2 + } + } + prepare_kwargs("POST", kwargs) + self.assertIn('"a": 1', kwargs["data"]) + self.assertIn('"b": 2', kwargs["data"]) + + def test_prepare_kwargs_content_type_application_json_charset_utf8(self): kwargs = { "headers": { "content-type": "application/json; charset=utf-8" @@ -47,5 +61,4 @@ class TestHttpClient(ApiServerUnittest): } } prepare_kwargs("POST", kwargs) - self.assertIn('"a": 1', kwargs["data"]) - self.assertIn('"b": 2', kwargs["data"]) + self.assertIsInstance(kwargs["data"], bytes)