Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CherryPy behind Nginx reverse-proxy POST requests corrupted/truncated

I have put my application using Cherrypy 3.1.2 behind Nginx configured as a reverse-proxy. All is working right for GET requests, but all POST requests return HTTP 400 - Malformed header.

I traced into CherryPy WSGI-Server source code to see the request-handling code and found out that if for GET requests the first request line correctly reads like for example:

GET /home HTTP/1.0

for POST requests it's like:

<HTTP headers truncated at front>

POST /home HTTP/1.0

So instead of the correctly formed request containing GET/POST request line followed by HTTP headers, for POST requests my application receives from Nginx:

  1. First HTTP header lines truncated from start by some number of bytes
  2. Then a blank line indicating end od HTTP headers
  3. THEN a "POST /home HTTP/1.0", that was clearly expected as a first line of the request.
  4. EDIT: That's the end of request, so there's also NO body data that should follow HTTP POST headers.

Additionally, the number of bytes of the truncation from p.1 seems to depend on how much POST data there is on a form, for example the more characters I type in /home FORM fields, the more characters into the HTTP headers are removed.

Apparently Nginx is somehow corrupting the header when it passes it to upstream server (my application).
BUT: when I just for test made Nginx redirect to some external web sites (using POST requests too) - everything goes fine.

So I'm now pretty stuck.

My configuration is: Windows XP Prof, Python/2.5.1, CherryPy/3.1.2, Nginx/0.8.32
Browsers: FireFox 2.0, IE 7.0
My application (running standalone) is generally working and tested under a number of configurations.

I use pretty basic Nginx config like:

upstream backend {
    server localhost:8088 weight=1;
}
server {
    listen 80;
    server_name  localhost;

    location / {
        #proxy_read_timeout 300;

        proxy_pass http://backend;
        #proxy_redirect default;
    }
}

Although tried many other examples and configurations of proxy_pass found on the net.

Any ideas where to look for the problem? Nginx configuration, my CherryPy app or elsewhere?

NEW: I found, that it works correctly but only for POST requests having zero body content length (made an empty without any fields to test that).
And verified that the count of bytes truncated from the begginning is equal to Content-length + some small const number (probably 2).

like image 438
Adam Kania Avatar asked Feb 16 '10 12:02

Adam Kania


1 Answers

you could try the parameters:

ignore_invalid_headers   on;
sendfile                 on;

in the http block... also might try disabling keepalives and ensure you're logging access/errors to debug.

like image 54
zeroasterisk Avatar answered Oct 20 '22 01:10

zeroasterisk