In the process of switching from Apache 2 to an all-nginx setup for
front-end servers I have found a nginx (miss-)feature that makes it
impossible to service certain clients. Basically nginx will refuse to
serve POST requests that don’t specify a Content-Length parameter and
use Transfer-Encoding: chunked for the POST client body. A 411 error
will be served every time such a request is received.
Setting up nginx as a proxy doesn’t work either, the same 411 error is
served. It appears nginx is buffering the POST body and applies the
same limiting rules even for proxy_pass-ed requests.
I’ve looked in the code and it appears to be an explicit limitation
(ngx_http_process_request_header() function in ngx_http_request.c),
and the changelog mentions it as an actual “bugfix” (nginx 0.3.12).
I’m not an expert in technolegalese but it appears that TE:chunked
POST bodies is a HTTP 1.1 feature and there are actual products
sending such POST bodies, and I am pretty sure other servers that
Apache 2 support it too. Is there any technical explanation for nginx
not supporting, or at least explicitly disabling it? Anybody knows a
work-around for it? I guess the correct answer is “add the feature and
send a patch”, but asking first to not reinvent any wheel won’t hurt
(The clients in question are J2ME phones. I can do my own HTTP client
for the few of them that expose TCP sockets to applications, but the
majority only allow high-level “HTTP connections” that don’t expose
any socket internals or details about how the actual request is
formatted. Not all of them are doing TE:chunked POST but the ones that
do are very significant, for example the official Sun J2ME emulator.)
Did you find a work around for this issue? I’m having the same issue as
believed. We have a system that uses a browser, java client, and a CAD
client. The first two can upload files fine except the last one.
Unfortunately I didn’t find a work around. I just went and set up a
dedicated Apache in a high port to serve the mobile clients (a
solution that has its own problems since it is common for mobile
carriers to block non-standard ports.)
If you are dealing with a desktop client app you may have some control
over its configuration. The problem comes mainly from HTTP 1.1 clients
assuming the server has full support for HTTP 1.1 features, like
chunked POST bodies. Try to force HTTP 1.0 in the client, that should
disable chunked POST.
I actually spent some time with the source of nginx. I was impressed
with the extremely optimized approach to everything, from I/O to
buffering to even string comparisons. It was also very tidy and
readable. Disabling the 411 error check was easy enough but the
buffering code for the POST body is written under the asumption that
its length is fully known in advance (i.e. from the Content-Length
header sent by the client.) Apparently it is legal for HTTP 1.1
clients to not send a Content-Length header and just rely on the
auto-finalizing feature of the chunked encoding (sending a 0 length
chunk.) The buffering code was not ready for this at all and would
have required extensive modifications. Having 0 experience with the
code it would take me way too long to come up with a working patch, so
I decided to just go back to Apache for the time being.
I’m having the same issue with nginx-0.7.21 - “on any POST with
Transfer-Encoding: chunked, I do receive: HTTP/1.1 411 Length Required”.
It’s not RFC complaint.
If a message is received with both a Transfer-Encoding header field and
a Content-Length header field, the latter MUST be ignored.
Maybe Igor will shed a light on the issue and tell us if there is a
plans for such feature in nginx.