diff --git a/django/http/__init__.py b/django/http/__init__.py index c6205ec953..60a92d5f1c 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -3,6 +3,7 @@ from __future__ import absolute_import import datetime import os import re +import sys import time import warnings @@ -177,6 +178,8 @@ def build_request_repr(request, path_override=None, GET_override=None, unicode(cookies), unicode(meta))) +class UnreadablePostError(IOError): + pass class HttpRequest(object): """A basic HTTP request.""" @@ -321,7 +324,10 @@ class HttpRequest(object): if not hasattr(self, '_body'): if self._read_started: raise Exception("You cannot access body after reading from request's data stream") - self._body = self.read() + try: + self._body = self.read() + except IOError, e: + raise UnreadablePostError, e, sys.exc_traceback self._stream = StringIO(self._body) return self._body diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py index e71c6f6eaa..d4239448dd 100644 --- a/tests/regressiontests/requests/tests.py +++ b/tests/regressiontests/requests/tests.py @@ -1,3 +1,5 @@ +from __future__ import with_statement + import time import warnings from datetime import datetime, timedelta @@ -6,7 +8,7 @@ from StringIO import StringIO from django.conf import settings from django.core.handlers.modpython import ModPythonRequest from django.core.handlers.wsgi import WSGIRequest, LimitedStream -from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_repr +from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_repr, UnreadablePostError from django.test.utils import get_warnings_state, restore_warnings_state from django.utils import unittest from django.utils.http import cookie_date @@ -430,3 +432,21 @@ class RequestsTests(unittest.TestCase): self.assertEqual(request.body, request.raw_post_data) finally: restore_warnings_state(warnings_state) + + + def test_POST_connection_error(self): + """ + If wsgi.input.read() raises an exception while trying to read() the + POST, the exception should be identifiable (not a generic IOError). + """ + class ExplodingStringIO(StringIO): + def read(self, len=0): + raise IOError("kaboom!") + + payload = 'name=value' + request = WSGIRequest({'REQUEST_METHOD': 'POST', + 'CONTENT_LENGTH': len(payload), + 'wsgi.input': ExplodingStringIO(payload)}) + + with self.assertRaises(UnreadablePostError): + request.raw_post_data