request.post () does not work correctly by generating a 301 redirect in Nginx

0

I'm having a problem when using request.post('url', data) , for some reason when the server receives this request, it redirects (301) the request to the same url by losing the POST data, ending as a GET method.

Python:

>>> r = requests.post('http://meusite.com/teste', data={'a': 'teste'})
>>> r.request.method
'GET'
>>> r.request.headers
{'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'python-requests/2.9.1'}
>>> r.request.body  # nao tem nada no body

>>> r.history  # analisando a historia do request é encontrado um redirecionamento 301
[<Response [301]>]
>>> history = r.history[0]
>>> history.request.method
'POST'
>>> history.request.headers
{'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'python-requests/2.9.1', 'Content-Length': '7'}
>>> history.request.body
'a=teste'

As you can see, when sending a POST, a 301 happens (as it is in r.history ) redirecting with a GET (losing data that had been passed by POST).

Nginx Log:

[01/Apr/2016:19:48:46 +0000] "POST /teste HTTP/1.1" 301 5 "-" "python-requests/2.9.1"
[01/Apr/2016:19:48:46 +0000] "GET /teste/ HTTP/1.1" 200 66 "-" "python-requests/2.9.1"

I tried to send this data via request.post() from both localhost to the target server, and through the target server itself, and it still has the same problem.

My Nginx is configured as follows:

Nginx:

upstream hello_django_app_server {
    server unix:/home/ubuntu/virtualenvs/hello_django/sockfile/gunicorn.sock fail_timeout=0;
}

server {
   listen 80;
   server_name hello_django.com;
   client_max_body_size 4G;
   keepalive_timeout 5;

   location / {
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_redirect off;
       if (!-f $request_filename) {
           proxy_pass http://hello_django_app_server;
           break;
       }
   }
}

He is using Gunicorn to serve Django.

Gunicorn:

#!/bin/bash

NAME="hello_app"                                  # Name of the application
DJANGODIR=/webapps/hello_django/hello             # Django project directory
SOCKFILE=/webapps/hello_django/run/gunicorn.sock  # we will communicte using this unix socket
USER=hello                                        # the user to run as
GROUP=webapps                                     # the group to run as
NUM_WORKERS=3                                     # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=hello.settings             # which settings file should Django use
DJANGO_WSGI_MODULE=hello.wsgi                     # WSGI module name

echo "Starting $NAME as 'whoami'"

# Activate the virtual environment
cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level=debug \
  --log-file=-
view rawgunicorn_start.bash

My project is working normally (I'm even following this site as a reference: link ). I can send forms internally via POST without problems. But when I use requests.post() it does not work, it seems like a Nginx problem.

I need to receive notifications from Amazon SNS, through HTTP it sends data via POST and I handle this data on my server.

My EC2 instance is configured both inbound and outbound to receive access of any type (alltrafic), so there are no instance access issues.

Everything indicates that the problem is in Nginx or still in Gunicorn, I do not know. How do I resolve this issue?

    
asked by anonymous 01.04.2016 / 22:33

1 answer

1

After writing down the question, I was able to find the problem. The URL of requests.post() has to end with \ , the fact that it is not ending, a redirect is occurring to the same URL with bars at the end, which ends up losing the data sent via POST.

After running the code it generated a 403 error related to the permission, which is nothing more than the lack of csrf for POST sending, placing the decorator @csrf_exempt ( from django.views.decorators.csrf import csrf_exempt ) in the view solved the problem.

    
01.04.2016 / 22:37