#4965 fix: Accessing response.content twice removes forgets read error.

This commit is contained in:
Белавин Денис
2019-05-14 12:11:56 +03:00
parent d91fe00983
commit bd10047244
2 changed files with 57 additions and 7 deletions
+16 -7
View File
@@ -640,7 +640,9 @@ class Response(object):
#: is a response.
self.request = None
self.error = None
#: If there was an error in the processing of content,
#: then save the error that would return the same error when you re-appeal.
self._error = None
def __enter__(self):
return self
@@ -751,15 +753,21 @@ class Response(object):
try:
for chunk in self.raw.stream(chunk_size, decode_content=True):
yield chunk
except ProtocolError as e:
self._error = e
raise ChunkedEncodingError(e)
self._error = ChunkedEncodingError(e)
except DecodeError as e:
self._error = e
raise ContentDecodingError(e)
self._error = ContentDecodingError(e)
except ReadTimeoutError as e:
self._error = e
raise ConnectionError(e)
self._error = ConnectionError(e)
finally:
# if we had an error - throw the saved error
if self._error:
raise self._error
else:
# Standard file-like object.
while True:
@@ -832,6 +840,7 @@ class Response(object):
else:
self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b''
# if we had an error - throw the saved error
if self._error is not None:
raise self._error
+41
View File
@@ -3,6 +3,7 @@
import pytest
import threading
import requests
from requests.exceptions import ChunkedEncodingError
from tests.testserver.server import Server, consume_socket_content
@@ -307,3 +308,43 @@ def test_fragment_update_on_redirect():
assert r.url == 'http://{}:{}/final-url/#relevant-section'.format(host, port)
close_server.set()
def test_response_content_retains_error():
"""Verify that accessing response.content retains an error.
See https://github.com/kennethreitz/requests/issues/4965
"""
data = "Some random stuff to read from remove server.\n"
def response_handler(sock):
req = consume_socket_content(sock, timeout=0.5)
# Send invalid chunked data (length mismatch)
sock.send(
b'HTTP/1.1 200 OK\r\n'
b'Transfer-Encoding: chunked\r\n'
b'\r\n2\r\n42\r\n8\r\n123\r\n' # 5 bytes missing
)
close_server = threading.Event()
server = Server(response_handler, wait_to_close_event=close_server)
with server as (host, port):
url = 'http://{}:{}/path'.format(host, port)
r = requests.post(url, stream=True)
with pytest.raises(ChunkedEncodingError):
r.content
# Access the bad response data again, I would expect the same
# error again.
try:
content = r.content
except ChunkedEncodingError:
pass # fine, same exception
else:
assert False, "error response has content: {0!r}".format(content)
close_server.set()