From 58d555caf527d6f1bdfeab14527484e4cca68648 Mon Sep 17 00:00:00 2001
From: Tim Graham <timograham@gmail.com>
Date: Tue, 8 Oct 2013 08:05:39 -0400
Subject: [PATCH] Fixed #16822 -- Added RawPostDataException

Thanks jaylett for the patch.
---
 django/http/__init__.py |  4 ++--
 django/http/request.py  | 11 ++++++++++-
 tests/requests/tests.py |  7 ++++---
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/django/http/__init__.py b/django/http/__init__.py
index be7b24b2e2..bd6429ffbb 100644
--- a/django/http/__init__.py
+++ b/django/http/__init__.py
@@ -1,6 +1,6 @@
 from django.http.cookie import SimpleCookie, parse_cookie
-from django.http.request import (HttpRequest, QueryDict, UnreadablePostError,
-    build_request_repr)
+from django.http.request import (HttpRequest, QueryDict, RawPostDataException,
+    UnreadablePostError, build_request_repr)
 from django.http.response import (HttpResponse, StreamingHttpResponse,
     HttpResponseRedirect, HttpResponsePermanentRedirect,
     HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden,
diff --git a/django/http/request.py b/django/http/request.py
index f19ccaf068..3972151865 100644
--- a/django/http/request.py
+++ b/django/http/request.py
@@ -31,6 +31,15 @@ class UnreadablePostError(IOError):
     pass
 
 
+class RawPostDataException(Exception):
+    """
+    You cannot access raw_post_data from a request that has
+    multipart/* POST data if it has been accessed via POST,
+    FILES, etc..
+    """
+    pass
+
+
 class HttpRequest(object):
     """A basic HTTP request."""
 
@@ -192,7 +201,7 @@ class HttpRequest(object):
     def body(self):
         if not hasattr(self, '_body'):
             if self._read_started:
-                raise Exception("You cannot access body after reading from request's data stream")
+                raise RawPostDataException("You cannot access body after reading from request's data stream")
             try:
                 self._body = self.read()
             except IOError as e:
diff --git a/tests/requests/tests.py b/tests/requests/tests.py
index b5edc09deb..45e219f345 100644
--- a/tests/requests/tests.py
+++ b/tests/requests/tests.py
@@ -12,7 +12,8 @@ from django.db import connection, connections, DEFAULT_DB_ALIAS
 from django.core import signals
 from django.core.exceptions import SuspiciousOperation
 from django.core.handlers.wsgi import WSGIRequest, LimitedStream
-from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_repr, UnreadablePostError
+from django.http import (HttpRequest, HttpResponse, parse_cookie,
+    build_request_repr, UnreadablePostError, RawPostDataException)
 from django.test import SimpleTestCase, TransactionTestCase
 from django.test.client import FakePayload
 from django.test.utils import override_settings, str_prefix
@@ -263,7 +264,7 @@ class RequestsTests(SimpleTestCase):
                                'CONTENT_LENGTH': len(payload),
                                'wsgi.input': payload})
         self.assertEqual(request.read(2), b'na')
-        self.assertRaises(Exception, lambda: request.body)
+        self.assertRaises(RawPostDataException, lambda: request.body)
         self.assertEqual(request.POST, {})
 
     def test_non_ascii_POST(self):
@@ -308,7 +309,7 @@ class RequestsTests(SimpleTestCase):
                                'CONTENT_LENGTH': len(payload),
                                'wsgi.input': payload})
         self.assertEqual(request.POST, {'name': ['value']})
-        self.assertRaises(Exception, lambda: request.body)
+        self.assertRaises(RawPostDataException, lambda: request.body)
 
     def test_body_after_POST_multipart_related(self):
         """