Fixed #17277 - Wrap IOErrors raised due to client disconnect in a specific IOError subclass so they can be distinguished from more serious errors. Thanks David Lowe.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17493 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Carl Meyer 2012-02-10 22:51:07 +00:00
parent 8be356ea99
commit 0ce6636102
2 changed files with 28 additions and 2 deletions

View File

@ -3,6 +3,7 @@ from __future__ import absolute_import
import datetime import datetime
import os import os
import re import re
import sys
import time import time
import warnings import warnings
@ -177,6 +178,8 @@ def build_request_repr(request, path_override=None, GET_override=None,
unicode(cookies), unicode(cookies),
unicode(meta))) unicode(meta)))
class UnreadablePostError(IOError):
pass
class HttpRequest(object): class HttpRequest(object):
"""A basic HTTP request.""" """A basic HTTP request."""
@ -321,7 +324,10 @@ class HttpRequest(object):
if not hasattr(self, '_body'): if not hasattr(self, '_body'):
if self._read_started: if self._read_started:
raise Exception("You cannot access body after reading from request's data stream") 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) self._stream = StringIO(self._body)
return self._body return self._body

View File

@ -1,3 +1,5 @@
from __future__ import with_statement
import time import time
import warnings import warnings
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -6,7 +8,7 @@ from StringIO import StringIO
from django.conf import settings from django.conf import settings
from django.core.handlers.modpython import ModPythonRequest from django.core.handlers.modpython import ModPythonRequest
from django.core.handlers.wsgi import WSGIRequest, LimitedStream 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.test.utils import get_warnings_state, restore_warnings_state
from django.utils import unittest from django.utils import unittest
from django.utils.http import cookie_date from django.utils.http import cookie_date
@ -430,3 +432,21 @@ class RequestsTests(unittest.TestCase):
self.assertEqual(request.body, request.raw_post_data) self.assertEqual(request.body, request.raw_post_data)
finally: finally:
restore_warnings_state(warnings_state) 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