#29427: RequestDataTooBig raised in request.py prevents Middleware from 
returning a
valid response
-----------------------------------------+------------------------
               Reporter:  S. Paquette    |          Owner:  nobody
                   Type:  Bug            |         Status:  new
              Component:  HTTP handling  |        Version:  1.11
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 This is effectively a request to re-open #28106, which was closed because
 the original author never replied to a request for more information.

 We need a way to return a response from a Middleware which is handling the
 RequestDataTooBig exception, but Middlewares intercepting this exception
 never generate a valid response. This seems due to how the exception
 causes self._body to never be created in request.py.

 In django.http.request, a check of the content length is done against
 settings.DATA_UPLOAD_MAX_MEMORY_SIZE at line 267.
 {{{
             # Limit the maximum request data size that will be handled in-
 memory.
             if (settings.DATA_UPLOAD_MAX_MEMORY_SIZE is not None and
                     int(self.META.get('CONTENT_LENGTH') or 0) >
 settings.DATA_UPLOAD_MAX_MEMORY_SIZE):
                 raise RequestDataTooBig('Request body exceeded
 settings.DATA_UPLOAD_MAX_MEMORY_SIZE.')

 }}}

 If the content length exceeds DATA_UPLOAD_MAX_MEMORY_SIZE, no request body
 is generated, and a RequestDataTooBig exception is raised.

 In order to detect this error and return a useful response to our users'
 browsers, we created a Middleware to catch the exception and supply an
 informative JsonResponse. However, despite the status setting correctly,
 the response itself was never being returned. Our Middleware:
 {{{
 from django.http import JsonResponse
 from django.core.exceptions import RequestDataTooBig


 class CheckSize(object):

     def __init__(self, get_response):
         self.get_response = get_response

     def __call__(self, request):

         try:
             body = request.body
         except RequestDataTooBig:
             return JsonResponse({"msg": "The file provided is too large.
 Please reduce its size and try again."}, status=400)

         response = self.get_response(request)
         return response
 }}}
 We tried placing the Middleware anywhere in the chain, and making it the
 only Middleware, but nothing worked.

 Per the author of #28106, we then added in an empty body to the request
 when the exception is raised, and that solved the problem:
 {{{
             # Limit the maximum request data size that will be handled in-
 memory.
             if (settings.DATA_UPLOAD_MAX_MEMORY_SIZE is not None and
                     int(self.META.get('CONTENT_LENGTH') or 0) >
 settings.DATA_UPLOAD_MAX_MEMORY_SIZE):
                 self._body = self.read(None)
                 raise RequestDataTooBig('Request body exceeded
 settings.DATA_UPLOAD_MAX_MEMORY_SIZE.')

 }}}

 After doing this, our response is returned. This can be reproduced on
 Django 1.11.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29427>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/053.39c05672e83fd1228c57234d24373b56%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to