mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-02 19:40:13 +03:00
Add docs for 'Request.http_request`
- Add docs for accessing the underlying 'HttpRequest' object, and warn users that doing so is considered to be advanced, non-standard usage. - Add tests about duplicate stream parsing assumptions, which warrant the above warning. These tests are currently failing due to a bug.
This commit is contained in:
parent
9bb17e4df6
commit
335ba0e377
|
@ -130,6 +130,9 @@ As REST framework's `Request` extends Django's `HttpRequest`, all the other stan
|
|||
|
||||
Note that due to implementation reasons the `Request` class does not inherit from `HttpRequest` class, but instead extends the class using composition.
|
||||
|
||||
# Accessing the HttpRequest
|
||||
|
||||
The underlying `HttpRequest` can be accessed through the `.http_request` attribute. While direct manipulation of the `HttpRequest` is discouraged, there are some advanced use cases that may require it. For example, one view may delegate request handling to a secondary view function. In this case, it is necessary to pass the original `HttpRequest` to the delegated view instead of the DRF `Request` object. Be aware that duplicate processing of the `HttpRequest` may have have unintended side effects. For example, if the request stream has already been consumed, it may not be accessible for a second read and will raise an exception.
|
||||
|
||||
[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
|
||||
[parsers documentation]: parsers.md
|
||||
|
|
|
@ -13,6 +13,7 @@ from django.contrib.auth.middleware import AuthenticationMiddleware
|
|||
from django.contrib.auth.models import User
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.http.request import RawPostDataException
|
||||
from django.test import TestCase, override_settings
|
||||
from django.utils import six
|
||||
|
||||
|
@ -137,6 +138,11 @@ class MockView(APIView):
|
|||
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):
|
||||
def post(self, request):
|
||||
filenames = [file.temporary_file_path() for file in request.FILES.values()]
|
||||
|
@ -149,6 +155,7 @@ class FileUploadView(APIView):
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^$', MockView.as_view()),
|
||||
url(r'^echo/$', EchoView.as_view()),
|
||||
url(r'^upload/$', FileUploadView.as_view())
|
||||
]
|
||||
|
||||
|
@ -311,3 +318,43 @@ class TestHttpRequest(TestCase):
|
|||
"`_request` has been deprecated in favor of "
|
||||
"`http_request`, and will be removed in 3.10"
|
||||
)
|
||||
|
||||
@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.http_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.http_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']}
|
||||
|
|
Loading…
Reference in New Issue
Block a user