#31533: Test client request's post body can be read multiple times, unlike real
requests
---------------------------------------------+------------------------
               Reporter:  Ben Beecher        |          Owner:  nobody
                   Type:  Bug                |         Status:  new
              Component:  Testing framework  |        Version:  3.0
               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                  |
---------------------------------------------+------------------------
 I have a DRF based signup flow that looks like this:



 {{{
     def post(self, request, *args, **kwargs):
         register_serializer = self.get_serializer(data=request.data)
         login_serializer =
 settings.SERIALIZERS.token_create(data=request.data)

         if register_serializer.is_valid():
             return self.create(request, *args, **kwargs)
         elif login_serializer.is_valid():
             return TokenCreateView.as_view()(request=request._request)
         else:
             register_serializer.is_valid(raise_exception=True)
 }}}
 In short - try to sign a user up, then try to log them in.

 with the following test I get a good response:


 {{{
     def test_register_but_really_login(self):
         response = self.client.post(self.url, self.form_data)
         self.assertEqual(response.status_code, s.HTTP_201_CREATED)
         response = self.client.post(self.url, self.form_data)
         self.assertEqual(response.status_code, s.HTTP_200_OK)

 }}}

 But when run for real I get this response with the same behavior:

 {{{
 10:57:18 backend.1  | 127.0.0.1 - - [03/May/2020 14:57:18] "POST
 /auth/register/ HTTP/1.1" 500 -
 10:57:18 backend.1  | Traceback (most recent call last):
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/contrib/staticfiles/handlers.py", line 68, in __call__
 10:57:18 backend.1  |     return self.application(environ, start_response)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/wsgi.py", line 133, in __call__
 10:57:18 backend.1  |     response = self.get_response(request)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/base.py", line 75, in get_response
 10:57:18 backend.1  |     response = self._middleware_chain(request)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/exception.py", line 36, in inner
 10:57:18 backend.1  |     response = response_for_exception(request, exc)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/exception.py", line 90, in
 response_for_exception
 10:57:18 backend.1  |     response = handle_uncaught_exception(request,
 get_resolver(get_urlconf()), sys.exc_info())
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/exception.py", line 125, in
 handle_uncaught_exception
 10:57:18 backend.1  |     return debug.technical_500_response(request,
 *exc_info)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django_extensions/management/technical_response.py", line 37, in
 null_technical_500_response
 10:57:18 backend.1  |     six.reraise(exc_type, exc_value, tb)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/six.py", line 702, in reraise
 10:57:18 backend.1  |     raise value.with_traceback(tb)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/exception.py", line 34, in inner
 10:57:18 backend.1  |     response = get_response(request)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/base.py", line 115, in _get_response
 10:57:18 backend.1  |     response =
 self.process_exception_by_middleware(e, request)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/core/handlers/base.py", line 113, in _get_response
 10:57:18 backend.1  |     response = wrapped_callback(request,
 *callback_args, **callback_kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/views/decorators/csrf.py", line 54, in wrapped_view
 10:57:18 backend.1  |     return view_func(*args, **kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/views/generic/base.py", line 71, in view
 10:57:18 backend.1  |     return self.dispatch(request, *args, **kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 505, in dispatch
 10:57:18 backend.1  |     response = self.handle_exception(exc)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 465, in handle_exception
 10:57:18 backend.1  |     self.raise_uncaught_exception(exc)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 476, in raise_uncaught_exception
 10:57:18 backend.1  |     raise exc
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 502, in dispatch
 10:57:18 backend.1  |     response = handler(request, *args, **kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/workspace/sampleapp/sampleapp/account/views.py", line 31,
 in post
 10:57:18 backend.1  |     return
 TokenCreateView.as_view()(request=request._request)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/views/decorators/csrf.py", line 54, in wrapped_view
 10:57:18 backend.1  |     return view_func(*args, **kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/views/generic/base.py", line 71, in view
 10:57:18 backend.1  |     return self.dispatch(request, *args, **kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 505, in dispatch
 10:57:18 backend.1  |     response = self.handle_exception(exc)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 465, in handle_exception
 10:57:18 backend.1  |     self.raise_uncaught_exception(exc)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 476, in raise_uncaught_exception
 10:57:18 backend.1  |     raise exc
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/views.py", line 502, in dispatch
 10:57:18 backend.1  |     response = handler(request, *args, **kwargs)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/djoser/utils.py", line 36, in post
 10:57:18 backend.1  |     serializer =
 self.get_serializer(data=request.data)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/request.py", line 209, in data
 10:57:18 backend.1  |     self._load_data_and_files()
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/request.py", line 272, in _load_data_and_files
 10:57:18 backend.1  |     self._data, self._files = self._parse()
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/request.py", line 322, in _parse
 10:57:18 backend.1  |     stream = self.stream
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/request.py", line 196, in stream
 10:57:18 backend.1  |     self._load_stream()
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/request.py", line 302, in _load_stream
 10:57:18 backend.1  |     self._stream = io.BytesIO(self.body)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/rest_framework/request.py", line 409, in __getattr__
 10:57:18 backend.1  |     return getattr(self._request, attr)
 10:57:18 backend.1  |   File
 "/home/bbeecher/.virtualenvs/sampleapp/lib/python3.8/site-
 packages/django/http/request.py", line 292, in body
 10:57:18 backend.1  |     raise RawPostDataException("You cannot access
 body after reading from request's data stream")
 10:57:18 backend.1  | django.http.request.RawPostDataException: You cannot
 access body after reading from request's data stream
 }}}

 The error message makes total sense - I am in fact trying to access the
 request body a second time. But I do the same thing in test successfully.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31533>
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/047.3386751ba51f766d5c5af447790757cf%40djangoproject.com.

Reply via email to