title: Django rest Framework empty response with gunicorn, but works with runserver
body: <p>I am trying to implement an Oauth2 authentication using <code>django-oauth-toolkit</code>, and the key exchange works when I am using the built-in django server. However, when I am using gunicorn, I have an empty response. All the other endpoints work fine with gunicorn:</p>
  
  <p><strong>gunicorn command</strong></p>
  
  <pre class="lang-sh prettyprint-override"><code>gunicorn --bind 127.0.0.1:8000 api_name.wsgi
  </code></pre>
  
  <p><strong>view.py</strong></p>
  
  <pre class="lang-py prettyprint-override"><code>
  from rest_framework.response import Response
  from rest_framework.decorators import api_view, permission_classes
  from rest_framework.permissions import AllowAny
  
  import requests
  
  
  from .serializers import CreateUserSerializer
  
  
  @api_view(['POST'])
  @permission_classes([AllowAny])
  def register(request):
      '''
      Registers user to the server. Input should be in the format:
      {"username": "username", "password": "1234abcd"}
      '''
      # Put the data from the request into the serializer
      serializer = CreateUserSerializer(data=request.data)
      # Validate the data
      if serializer.is_valid():
          # If it is valid, save the data (creates a user).
          serializer.save()
          # Then we get a token for the created user.
          # This could be done differentley
          r = requests.post('http://127.0.0.1:8000/o/token/', data={
                  'grant_type': 'password',
                  'username': request.data['username'],
                  'password': request.data['password'],
                  'client_id': get_client_id(),
                  'client_secret': get_client_secret(),
              },
          )
          return Response(r.json())
      return Response(serializer.errors)
  
  
  @api_view(['POST'])
  @permission_classes([AllowAny])
  def token(request):
      '''
      Gets tokens with username and password. Input should be in the format:
      {"username": "username", "password": "1234abcd"}
      '''
      r = requests.post('http://127.0.0.1:8000/o/token/', data={
              'grant_type': 'password',
              'username': request.data['username'],
              'password': request.data['password'],
              'client_id': get_client_id(),
              'client_secret': get_client_secret(),
              },
      )
      return Response(r.json())
  
  
  @api_view(['POST'])
  @permission_classes([AllowAny])
  def refresh_token(request):
      '''
      Registers user to the server. Input should be in the format:
      {"refresh_token": "&lt;token&gt;"}
      '''
      r = requests.post('http://127.0.0.1:8000/o/token/', data={
              'grant_type': 'refresh_token',
              'refresh_token': request.data['refresh_token'],
              'client_id': get_client_id(),
              'client_secret': get_client_secret(),
          },
      )
      return Response(r.json())
  
  
  @api_view(['POST'])
  @permission_classes([AllowAny])
  def revoke_token(request):
      '''
      Method to revoke tokens.
      {"token": "&lt;token&gt;"}
      '''
      r = requests.post( 'http://127.0.0.1:8000/o/revoke_token/', data={
              'token': request.data['token'],
              'client_id': get_client_id(),
              'client_secret': get_client_secret(),
          },
      )
      # If it goes well return sucess message (would be empty otherwise)
      if r.status_code == requests.codes.ok:
          return Response({'message': 'token revoked'}, r.status_code)
      # Return the error if it goes badly
      return Response(r.json(), r.status_code)
  </code></pre>
  
  <p><strong>urls.py</strong></p>
  
  <pre class="lang-py prettyprint-override"><code>from django.urls import path
  
  from . import views
  
  urlpatterns = [
      path('register/', views.register),
      path('token/', views.token),
      path('token/refresh/', views.refresh_token),
      path('token/revoke/', views.revoke_token),
  ]
  </code></pre>
  
  <p>when I launch the request:</p>
  
  <pre class="lang-sh prettyprint-override"><code>curl -d "username=new_user&amp;password=12345abcd" "127.0.0.1:8000/authentication/register/" -v
  </code></pre>
  
  <p>I have the responses:</p>
  
  <p>with <strong>django manage.py runserver</strong>:</p>
  
  <pre class="lang-sh prettyprint-override"><code>*   Trying 127.0.0.1...
  * TCP_NODELAY set
  * Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
  &gt; POST /authentication/register/ HTTP/1.1
  &gt; Host: 127.0.0.1:8000
  &gt; User-Agent: curl/7.58.0
  &gt; Accept: */*
  &gt; Content-Length: 37
  &gt; Content-Type: application/x-www-form-urlencoded
  &gt; 
  * upload completely sent off: 37 out of 37 bytes
  &lt; HTTP/1.1 200 OK
  &lt; Date: Tue, 31 Mar 2020 09:55:21 GMT
  &lt; Server: WSGIServer/0.2 CPython/3.6.2
  &lt; Content-Type: application/json
  &lt; Vary: Accept, Authorization, Cookie
  &lt; Allow: POST, OPTIONS
  &lt; X-Frame-Options: SAMEORIGIN
  &lt; Content-Length: 160
  &lt; 
  * Connection #0 to host 127.0.0.1 left intact
  
  {"access_token":"&lt;access-token&gt;","expires_in":36000,"token_type":"Bearer","scope":"read write","refresh_token":"&lt;refresh-token&gt;"}%
  </code></pre>
  
  <p>with <strong>gunicorn</strong>:</p>
  
  <pre class="lang-sh prettyprint-override"><code>*   Trying 127.0.0.1...
  * TCP_NODELAY set
  * Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
  &gt; POST /authentication/register/ HTTP/1.1
  &gt; Host: 127.0.0.1:8000
  &gt; User-Agent: curl/7.58.0
  &gt; Accept: */*
  &gt; Content-Length: 37
  &gt; Content-Type: application/x-www-form-urlencoded
  &gt; 
  * upload completely sent off: 37 out of 37 bytes
  * Empty reply from server
  * Connection #0 to host 127.0.0.1 left intact
  
  curl: (52) Empty reply from server
  </code></pre>
  
  <p><strong>gunicorn log</strong></p>
  
  <pre class="lang-sh prettyprint-override"><code>[2020-03-31 12:11:03 +0200] [3639] [INFO] Starting gunicorn 20.0.4
  [2020-03-31 12:11:03 +0200] [3639] [INFO] Listening at: http://127.0.0.1:8000 (3639)
  [2020-03-31 12:11:03 +0200] [3639] [INFO] Using worker: sync
  [2020-03-31 12:11:03 +0200] [3686] [INFO] Booting worker with pid: 3686
  [2020-03-31 12:11:46 +0200] [3639] [CRITICAL] WORKER TIMEOUT (pid:3686)
  </code></pre>