Browse Source

Fixed #18481 -- Wrapped request.FILES read error in UnreadablePostError

Thanks KyleMac for the report, André Cruz for the initial patch and
Hiroki Kiyohara for the tests.
Claude Paroz 12 years ago
parent
commit
de66b56790
2 changed files with 26 additions and 2 deletions
  1. 8 2
      django/http/request.py
  2. 18 0
      tests/requests/tests.py

+ 8 - 2
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:

+ 18 - 0
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:'),