From 03737bf9d41184719bf78782e44ec61b69794e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA?= Date: Sat, 5 Jan 2019 00:58:13 +0500 Subject: [PATCH] Do not strip body before JSON decoding + do not return None on empty body (#3482) This commit actually reverts 6a19364dc4c2591b38efa9410178d48447248e34 --- CHANGES/3482.bugfix | 1 + aiohttp/client_reqrep.py | 8 ++------ tests/test_client_response.py | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 CHANGES/3482.bugfix diff --git a/CHANGES/3482.bugfix b/CHANGES/3482.bugfix new file mode 100644 index 00000000000..8d193f45efb --- /dev/null +++ b/CHANGES/3482.bugfix @@ -0,0 +1 @@ +Do not return `None` on `await response.json()` when body is empty. Instead, raise `json.JSONDecodeError` as expected. diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index 5ef133bf325..dac1a0c9ab3 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -692,7 +692,7 @@ def __init__(self, method: str, url: URL, *, self._real_url = url self._url = url.with_fragment(None) - self._body = None # type: Any + self._body = None # type: bytes self._writer = writer # type: Optional[asyncio.Task[None]] self._continue = continue100 # None by default self._closed = True @@ -1028,14 +1028,10 @@ async def json(self, *, encoding: str=None, 'unexpected mimetype: %s' % ctype), headers=self.headers) - stripped = self._body.strip() # type: ignore - if not stripped: - return None - if encoding is None: encoding = self.get_encoding() - return loads(stripped.decode(encoding)) + return loads(self._body.decode(encoding)) async def __aenter__(self) -> 'ClientResponse': return self diff --git a/tests/test_client_response.py b/tests/test_client_response.py index c61998de8b7..920ca8ced98 100644 --- a/tests/test_client_response.py +++ b/tests/test_client_response.py @@ -3,6 +3,7 @@ import gc import sys +from json import JSONDecodeError from unittest import mock import pytest @@ -486,6 +487,29 @@ def side_effect(*args, **kwargs): assert response._connection is None +async def test_json_empty_body(loop, session) -> None: + response = ClientResponse('get', URL('http://def-cl-resp.org'), + request_info=mock.Mock(), + writer=mock.Mock(), + continue100=None, + timer=TimerNoop(), + traces=[], + loop=loop, + session=session) + + def side_effect(*args, **kwargs): + fut = loop.create_future() + fut.set_result(b'') + return fut + + response._headers = {'Content-Type': 'application/json'} + content = response.content = mock.Mock() + content.read.side_effect = side_effect + + with pytest.raises(JSONDecodeError): + await response.json() + + async def test_json_extended_content_type(loop, session) -> None: response = ClientResponse('get', URL('http://def-cl-resp.org'), request_info=mock.Mock(),