Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap exceptions caused by parsers in ParseError in request wrapper #9453

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion rest_framework/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,14 +356,17 @@ def _parse(self):

try:
parsed = parser.parse(stream, media_type, self.parser_context)
except Exception:
except Exception as exc:
# If we get an exception during parsing, fill in empty data and
# re-raise. Ensures we don't simply repeat the error when
# attempting to render the browsable renderer response, or when
# logging the request or similar.
self._data = QueryDict('', encoding=self._request._encoding)
self._files = MultiValueDict()
self._full_data = self._data
if isinstance(exc, AttributeError):
raise exceptions.ParseError(str(exc))

raise

# Parser classes may return the raw data, or a
Expand Down
21 changes: 21 additions & 0 deletions tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from rest_framework import status
from rest_framework.authentication import SessionAuthentication
from rest_framework.exceptions import ParseError
from rest_framework.parsers import BaseParser, FormParser, MultiPartParser
from rest_framework.request import Request, WrappedAttributeError
from rest_framework.response import Response
Expand Down Expand Up @@ -52,6 +53,14 @@ def parse(self, stream, media_type=None, parser_context=None):
return stream.read()



class BrokenParser(BaseParser):
media_type = 'text/plain'

def parse(self, stream, media_type=None, parser_context=None):
raise AttributeError


class TestContentParsing(TestCase):
def test_standard_behaviour_determines_no_content_GET(self):
"""
Expand Down Expand Up @@ -126,6 +135,18 @@ def test_standard_behaviour_determines_non_form_content_PUT(self):
request.parsers = (PlainTextParser(), )
assert request.data == content

def test_request_data_with_broken_parser(self):
"""
Ensure request.data raise ParseError if anything went wrong during parsing
"""
content = b'qwerty'
content_type = 'text/plain'
request = Request(factory.post('/', content, content_type=content_type))
request.parsers = (BrokenParser(), )
with self.assertRaises(ParseError):
request.data



class MockView(APIView):
authentication_classes = (SessionAuthentication,)
Expand Down
Loading