diff --git a/AUTHORS.rst b/AUTHORS.rst index e684d850..37b66698 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -165,3 +165,4 @@ Patches and Suggestions - Brian Samek (`@bsamek `_) - Dmitry Dygalo (`@Stranger6667 `_) - piotrjurkiewicz +- Jesse Shapiro (`@haikuginger `_) diff --git a/requests/models.py b/requests/models.py index 0c10eef1..67747405 100644 --- a/requests/models.py +++ b/requests/models.py @@ -420,8 +420,12 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): length = None if not data and json is not None: + # urllib3 requires a bytes-like body. Python 2's json.dumps + # provides this natively, but Python 3 gives a Unicode string. content_type = 'application/json' body = complexjson.dumps(json) + if not isinstance(body, bytes): + body = body.encode('utf-8') is_stream = all([ hasattr(data, '__iter__'), diff --git a/tests/test_requests.py b/tests/test_requests.py index 4bcf4536..167d5ca7 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1528,6 +1528,18 @@ class RedirectSession(SessionRedirectMixin): return string +def test_json_encodes_as_bytes(): + # urllib3 expects bodies as bytes-like objects + body = {"key": "value"} + p = PreparedRequest() + p.prepare( + method='GET', + url='https://www.example.com/', + json=body + ) + assert isinstance(p.body, bytes) + + def test_requests_are_updated_each_time(httpbin): session = RedirectSession([303, 307]) prep = requests.Request('POST', httpbin('post')).prepare()