Nginx connection reset, response from uWsgi lost
Asked Answered
W

4

23

I have a django app hosted via Nginx and uWsgi. In a certain very simple request, I get different behaviour for GET and POST, which should not be the case.

The uWsgi daemon log:

[pid: 32454|app: 0|req: 5/17] 127.0.0.1 () {36 vars in 636 bytes} [Tue Oct 19 11:18:36 2010] POST /buy/76d4f520ae82e1dfd35564aed64a885b/a_2/10/ => generated 80 bytes in 3 msecs (HTTP/1.0 440) 1 headers in 76 bytes (0 async switches on async core 0)
[pid: 32455|app: 0|req: 5/18] 127.0.0.1 () {32 vars in 521 bytes} [Tue Oct 19 11:18:50 2010] GET /buy/76d4f520ae82e1dfd35564aed64a885b/a_2/10/ => generated 80 bytes in 3 msecs (HTTP/1.0 440) 1 headers in 76 bytes (0 async switches on async core 0)

The Nginx accesslog:

127.0.0.1 - - [19/Oct/2010:18:18:36 +0200] "POST /buy/76d4f520ae82e1dfd35564aed64a885b/a_2/10/ HTTP/1.0" 440 0 "-" "curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15"
127.0.0.1 - - [19/Oct/2010:18:18:50 +0200] "GET /buy/76d4f520ae82e1dfd35564aed64a885b/a_2/10/ HTTP/1.0" 440 80 "-" "curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15"

The Nginx errorlog:

2010/10/19 18:18:36 [error] 4615#0: *5 readv() failed (104: Connection reset by peer) while reading upstream, client: 127.0.0.1, server: localhost, request: "POST /buy/76d4f520ae82e1dfd35564aed64a885b/a_2/10/ HTTP/1.0", upstream: "uwsgi://unix:sock/uwsgi.sock:", host: "localhost:9201"

In essence, Nginx somewhere loses the response if I use POST, not so if I use GET.

Anybody knows something about that?

Willful answered 19/10, 2010 at 16:26 Comment(1)
See also #7274225Opposition
W
1

After a lucky find in further research (http://answerpot.com/showthread.php?577619-Several%20Bugs/Page2) I found something that helped...

Supplying the uwsgi_pass_request_body off; parameter in the Nginx conf resolves this problem...

Willful answered 19/10, 2010 at 16:36 Comment(2)
This doesn't work if your app actually needs the POST data, right?Massengale
Yeah this will not past the post data to uwsgi. Instead post-buffering should be turned on.Cy
M
28

Pass --post-buffering 1 to uwsgi

This will automatically buffer all the http body > 1 byte

The problem is raised by the way nginx manages upstream disconnections

Muff answered 25/2, 2011 at 6:58 Comment(5)
FWIW, @Muff is the author of uwsgi.Opposition
This is really the correct answer. It is an option to uwsgi and you probably want to use it conjunction with --limit-post. projects.unbit.it/uwsgi/wiki/DocCy
I'm having a similar problem (only it has nothing to do with POSTs). Tried, the post-buffering and also @ehabkost's ForcePostHandler, but no luck. This is driving me nuts, please help!!! #18667870Vantage
Never mind! I was able to solve the problem by adding buffer-size = 8192 to uwsgi. Boy, was that hard to figure out...Vantage
Wouldn't that be a big performance issue, though? uWSGI's doc says this will save all HTTP body bigger than the limit specified. Saving the body to disk for every POST request could be an issue.Inhalation
M
5

I hit the same issue, but on my case I can't disable "uwsgi_pass_request_body" as most times (but not always) my app do need the POST data.

This is the workaround I found, while this issue is not fixed in uwsgi: http://permalink.gmane.org/gmane.comp.python.wsgi.uwsgi.general/813

import django.core.handlers.wsgi
class ForcePostHandler(django.core.handlers.wsgi.WSGIHandler):
    """Workaround for: http://lists.unbit.it/pipermail/uwsgi/2011-February/001395.html
    """
    def get_response(self, request):
        request.POST # force reading of POST data
        return super(ForcePostHandler, self).get_response(request)

application = ForcePostHandler()
Massengale answered 18/2, 2011 at 15:58 Comment(4)
This actually worked for me too (in my case with Flask project). Basically you need to read the POST before responding.Bul
@VictorFarazdagi how did you do that in Flask?Cartogram
Here's how as I just did to get around this obnoxious problem: response.dataMan
@roberto's answer is the correct one. Otherwise large POSTs will be stored in memory and not buffered to disk.Cy
D
5

I am facing the same issues. I tried all solutions above, but they were not working. Ignoring the response body in my case is simply not an option.

Apparently it is a bug with nginx and uwsgi when dealing with POST requests whose response is smaller than 4052 bytes

What solved it for me was adding "--pep3333-input" to the parameter list of uwsgi. After that all POSTs are returned correctly.

Versions of nginx/uwsgi I'm using:

$ nginx -V
nginx: nginx version: nginx/0.9.6

$ uwsgi --version
uWSGI 0.9.7
Dett answered 12/6, 2011 at 6:5 Comment(3)
Thanks for the answer. Just adding "--pep3333-input" to uwsgi didn't fix it. I also had to add "--post-buffering 4096" as referenced here: comments.gmane.org/gmane.comp.python.wsgi.uwsgi.general/812Attractant
According to Roberto, the --pep3333-input is now obsolete and doesn't do anything on newer versions of uwsgi. I removed the flag and things are still running correctly. Perhaps you are facing some other issue that you managed to solve with --post-buffering?Dett
If the issue in the question is the same as the issue I had, the problem was that if your your python code never reads the POST data (in django, this would be accessing request.POST somewhere in your view), then things get screwed up. If you tell UWSGI to buffer the POST data with the --post-buffering 1 parameter as roberto says, then your POST requests won't error no matter what you are doing in your view.Attractant
W
1

After a lucky find in further research (http://answerpot.com/showthread.php?577619-Several%20Bugs/Page2) I found something that helped...

Supplying the uwsgi_pass_request_body off; parameter in the Nginx conf resolves this problem...

Willful answered 19/10, 2010 at 16:36 Comment(2)
This doesn't work if your app actually needs the POST data, right?Massengale
Yeah this will not past the post data to uwsgi. Instead post-buffering should be turned on.Cy

© 2022 - 2024 — McMap. All rights reserved.