diff --git a/django/http/request.py b/django/http/request.py index e6811aa6ccd..37aa1a355a6 100644 --- a/django/http/request.py +++ b/django/http/request.py @@ -238,11 +238,17 @@ class HttpRequest(object): def read(self, *args, **kwargs): self._read_started = True - return self._stream.read(*args, **kwargs) + try: + return self._stream.read(*args, **kwargs) + except IOError as e: + six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2]) def readline(self, *args, **kwargs): self._read_started = True - return self._stream.readline(*args, **kwargs) + try: + return self._stream.readline(*args, **kwargs) + except IOError as e: + six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2]) def xreadlines(self): while True: diff --git a/tests/requests/tests.py b/tests/requests/tests.py index 676cd056792..4d730bb561c 100644 --- a/tests/requests/tests.py +++ b/tests/requests/tests.py @@ -659,6 +659,24 @@ class RequestsTests(SimpleTestCase): with self.assertRaises(UnreadablePostError): request.body + def test_FILES_connection_error(self): + """ + If wsgi.input.read() raises an exception while trying to read() the + FILES, the exception should be identifiable (not a generic IOError). + """ + class ExplodingBytesIO(BytesIO): + def read(self, len=0): + raise IOError("kaboom!") + + payload = b'x' + request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary=foo_', + 'CONTENT_LENGTH': len(payload), + 'wsgi.input': ExplodingBytesIO(payload)}) + + with self.assertRaises(UnreadablePostError): + request.FILES + @skipIf(connection.vendor == 'sqlite' and connection.settings_dict['NAME'] in ('', ':memory:'),