Hi,
We are trying to use post_action in a location block that only has
“return 202;”. Everything works fine for GET requests and with small
POST requests, but if the client request body + headers are over 1kB,
nginx will not trigger the post_action handler.
Test configuration, and debug log attached. Following commands can be
used to trigger the error:
dd if=/dev/zero of=request_body count=2
wget -d --post-file=request_body localhost:8022
Is this a bug or just the way it should work? I tested it with nginx
1.0.5 and 1.1.0, both appear to be working the same way.
I worked around it by creating a small module that just calls
ngx_http_read_client_request_body() and returns 202 from the callback.
But I feel that it might not be the right solution for this. (module
also attached)
Also while debugging I found another possibly related bug, if you do a
POST request against location / { return 202; } block, it will
incorrectly result in 2 lines in access log:
127.0.0.1 - - [10/Aug/2011:14:07:40 +0300] “POST / HTTP/1.1” 202 0 “-”
“curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o
zlib/1.2.3.4 libidn/1.18”
127.0.0.1 - - [10/Aug/2011:14:07:40 +0300] “foobar=foo” 400 172 “-” “-”
Happy to provide more information if needed. Thanks,
Pyry
Thank you for your report. Please try the attached patch.
Thank you, the patch appears to be working fine, but because it
discards the request body, it isn’t going to work for our use case.
Our use case is, to POST data to nginx and let nginx asynchronously
proxy it to somewhere else for processing, while freeing the client
that did the POSTing to do other things.
I think the request body should be transferred to post_action
location, and the location can then decide if it needs it or not.
Attached is a patch against 1.0.5 that reads the body if post_action
is used, but I’m not really sure if it’s correct. My nginx-fu is still
a bit lacking.
Thanks,
Pyry
Hello!
On Wed, Aug 10, 2011 at 02:18:41PM +0300, Pyry Hakulinen wrote:
dd if=/dev/zero of=request_body count=2
Also while debugging I found another possibly related bug, if you do a
POST request against location / { return 202; } block, it will
incorrectly result in 2 lines in access log:
127.0.0.1 - - [10/Aug/2011:14:07:40 +0300] “POST / HTTP/1.1” 202 0 “-”
“curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o
zlib/1.2.3.4 libidn/1.18”
127.0.0.1 - - [10/Aug/2011:14:07:40 +0300] “foobar=foo” 400 172 “-” “-”
Happy to provide more information if needed. Thanks,
Pyry
Thank you for your report. Please try the attached patch.
Maxim D.
Hello!
On Thu, Aug 11, 2011 at 02:38:44PM +0300, Pyry Hakulinen wrote:
location, and the location can then decide if it needs it or not.
Attached is a patch against 1.0.5 that reads the body if post_action
is used, but I’m not really sure if it’s correct. My nginx-fu is still
a bit lacking.
No, this is incorrect. Body should be either read or discarded
before response could be returned (else communication with clients
which write body and only then read response will just deadlock).
And it’s up to code returning response to decide whether it needs
body or not, post_action has nothing to do with it. (I personally
consider post_action to be a dirty hack which should be removed
entirely, and it’s not officially documented on purpose, but
that’s another story.)
In you particular case I would recommend actually using module to
read body and return 202 response instead of using “return 202”.
Maxim D.
Howdy,
No, this is incorrect. Body should be either read or discarded
before response could be returned (else communication with clients
which write body and only then read response will just deadlock).
Ah, indeed, I see what you mean. I didn’t see it deadlock, but I
really didn’t test it all that much. Thanks for looking.
(I personally consider post_action to be a dirty hack which should
be removed entirely, and it’s not officially documented on purpose,
but that’s another story.)
Yeah, it looks like it isn’t that reliable when used with POST
requests. For example, using this:
location / {
proxy_pass http://some.server;
post_action @post;
}
location @post {
proxy_pass http://some.server;
}
post_action will fail when client request body is buffered to a temp
file. Can be “fixed” by increasing client_body_buffer_size or by
discarding request body in @post location (proxy_pass_request_body
off; proxy_set_header Content-Length 0;).
In you particular case I would recommend actually using module to
read body and return 202 response instead of using “return 202”.
Thanks, this is probably what we will end up doing.
-Pyry