Test duplicate request stream parsing

This commit is contained in:
Ryan P Kilby 2018-01-25 06:35:18 -05:00
parent 9c85471c90
commit 5de278cb31

View File

@ -13,6 +13,7 @@ from django.contrib.auth.middleware import AuthenticationMiddleware
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sessions.middleware import SessionMiddleware from django.contrib.sessions.middleware import SessionMiddleware
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.http.request import RawPostDataException
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from django.utils import six from django.utils import six
@ -137,6 +138,11 @@ class MockView(APIView):
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class EchoView(APIView):
def post(self, request):
return Response(status=status.HTTP_200_OK, data=request.data)
class FileUploadView(APIView): class FileUploadView(APIView):
def post(self, request): def post(self, request):
filenames = [file.temporary_file_path() for file in request.FILES.values()] filenames = [file.temporary_file_path() for file in request.FILES.values()]
@ -149,6 +155,7 @@ class FileUploadView(APIView):
urlpatterns = [ urlpatterns = [
url(r'^$', MockView.as_view()), url(r'^$', MockView.as_view()),
url(r'^echo/$', EchoView.as_view()),
url(r'^upload/$', FileUploadView.as_view()) url(r'^upload/$', FileUploadView.as_view())
] ]
@ -292,3 +299,43 @@ class TestHttpRequest(TestCase):
message = "'Request' object has no attribute 'inner_property'" message = "'Request' object has no attribute 'inner_property'"
with self.assertRaisesMessage(AttributeError, message): with self.assertRaisesMessage(AttributeError, message):
request.inner_property request.inner_property
@override_settings(ROOT_URLCONF='tests.test_request')
def test_duplicate_request_stream_parsing_exception(self):
"""
Check assumption that duplicate stream parsing will result in a
`RawPostDataException` being raised.
"""
response = APIClient().post('/echo/', data={'a': 'b'}, format='json')
request = response.renderer_context['request']
# ensure that request stream was consumed by json parser
assert request.content_type.startswith('application/json')
assert response.data == {'a': 'b'}
# pass same HttpRequest to view, stream already consumed
with pytest.raises(RawPostDataException):
EchoView.as_view()(request._request)
@override_settings(ROOT_URLCONF='tests.test_request')
def test_duplicate_request_form_data_access(self):
"""
Form data is copied to the underlying django request for middleware
and file closing reasons. Duplicate processing of a request with form
data is 'safe' in so far as accessing `request.POST` does not trigger
the duplicate stream parse exception.
"""
response = APIClient().post('/echo/', data={'a': 'b'})
request = response.renderer_context['request']
# ensure that request stream was consumed by form parser
assert request.content_type.startswith('multipart/form-data')
assert response.data == {'a': ['b']}
# pass same HttpRequest to view, form data set on underlying request
response = EchoView.as_view()(request._request)
request = response.renderer_context['request']
# ensure that request stream was consumed by form parser
assert request.content_type.startswith('multipart/form-data')
assert response.data == {'a': ['b']}