| Issue 114: | Unable to POST with missing "Content-Length" header (for "Transfer-Encoding: chunked" requests) | |
| 10 people starred this issue and may be notified of changes. | Back to list |
Sign in to add a comment
|
What steps will reproduce the problem?
1. Make a POST request using "Transfer-Encoding: Chunked"
What is the expected output? What do you see instead?
The POST request should be successful. Instead, I receive a "HTTP/1.1 411
Length Required" response.
What version of the product are you using? On what operating system?
I'm running Ubuntu 7.10, Apache 2.2.4 and Passenger 2.0.2.
Please provide any additional information below.
Many mobile devices will make POST requests using "chunked" as the transfer
encoding, since their memory constraints may prohibit them from being able
to determine the full content-length at request time. Apache 1 had
difficulties with chunked POST requests due to relying on content-length,
but Apache 2 has since resolved the problem as per the requirements of HTTP
1.1 ("All HTTP/1.1 applications MUST be able to receive and decode the
"chunked" transfer-coding").
It seems as though Passenger is still using the Apache 1.3 API
(ap_setup_client_block on line 651 of ext/apache2/Hooks.cpp), which means
that the minute it sees a request missing a content-length parameter, it
immediately responds with "411 Length Required".
Unfortunately, I have no C++ *or* Apache experience, so I'm not really able
to help fix the problem.
The following is the output of running CURL, with and without chunked
encoding enabled:
$ curl -vvv -F "query=zoooom" --header "Transfer-Encoding: chunked"
http://localhost/stories/search.json
* About to connect() to localhost port 80 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> POST /stories/search.json HTTP/1.1
> User-Agent: curl/7.16.4 (i486-pc-linux-gnu) libcurl/7.16.4 OpenSSL/0.9.8e
zlib/1.2.3.3 libidn/1.0
> Host: localhost
> Accept: */*
> Transfer-Encoding: chunked
> Expect: 100-continue
> Content-Type: multipart/form-data;
boundary=----------------------------788d73dee5fa
>
< HTTP/1.1 411 Length Required
< Date: Thu, 31 Jul 2008 07:44:26 GMT
< Server: Apache/2.2.4 (Ubuntu) Phusion_Passenger/2.0.2
< Content-Length: 337
< Connection: close
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>411 Length Required</title>
</head><body>
<h1>Length Required</h1>
<p>A request of the requested method POST requires a valid
Content-length.<br />
</p>
<hr>
<address>Apache/2.2.4 (Ubuntu) Phusion_Passenger/2.0.2 Server at localhost
Port 80</address>
</body></html>
* Closing connection #0
$ curl -vvv -F "query=zoooom" http://localhost/stories/search.json
* About to connect() to localhost port 80 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> POST /stories/search.json HTTP/1.1
> User-Agent: curl/7.16.4 (i486-pc-linux-gnu) libcurl/7.16.4 OpenSSL/0.9.8e
zlib/1.2.3.3 libidn/1.0
> Host: localhost
> Accept: */*
> Content-Length: 146
> Expect: 100-continue
> Content-Type: multipart/form-data;
boundary=----------------------------0bf6b81d0f2c
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Thu, 31 Jul 2008 07:44:40 GMT
< Server: Apache/2.2.4 (Ubuntu) Phusion_Passenger/2.0.2
< X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.0.2
< X-Runtime: 0.22812
< ETag: "fea15ab349247b6d18f4975d50c65d12"
< Cache-Control: private, max-age=0, must-revalidate
< Set-Cookie: _sr_session=f812b50fb6c9f16cbb0728c19bc4dbaf; path=/
< Content-Length: 83
< Content-Type: text/javascript; charset=utf-8
<
* Connection #0 to host localhost left intact
* Closing connection #0
{"YAY": "JSON RETURNED"}
|
||||||||||||
,
Jul 31, 2008
Unfortunately I'm not aware of any other way with which Apache modules can receive POST bodies. The Apache API is not very well documented. If anybody knows how to fix this, please comment here.
Labels: NeedHelp
|
|||||||||||||
,
Aug 03, 2008
I'm not C++ programmer, but from looking around it seems as though you need to change the way you're using the ap_setup_client_block() API. This means using REQUEST_CHUNKED_DECHUNK instead of REQUEST_CHUNKED_ERROR, and never assuming that there is a Content-Length header. I've created a patch with these changes, but it's causing issues with the ap_content_length_filter (when I make the above chunked request, only the header of the HTTP request gets delivered to the Rails process and the body gets dropped with the error: "Connection reset by peer: ap_content_length_filter: apr_bucket_read() failed"). More competent C++ programmers like yourselves might be able to take this patch and make it work properly. |
|||||||||||||
,
Aug 04, 2008
Thanks. Are there any web browsers out there that can send POST data in chunked format? If not, could you use Wireshark or something to capture an HTTP session with chunked POST data, and attach it here? |
|||||||||||||
,
Aug 05, 2008
I'm not sure whether IE/Safari/Firefox etc. will use "Tranfer-Encoding: Chunked" under any conditions, but there may be a Firefox extension that allows you to do it. The alternative is to use curl as follows: curl -vvv \ -F "query=zoooom" \ --header "Transfer-Encoding: chunked" \ --header "Expect:" \ http://ooboontoo:81/stories/search.json I've attached the Wireshark output from the above curl command. |
|||||||||||||
,
Aug 06, 2008
This might be useful for some context: https://issues.rpath.com/browse/RPL-1174 |
|||||||||||||
,
Aug 07, 2008
Allright, thanks. I don't have time to do this right now, but it's on my todo list. |
|||||||||||||
,
Aug 07, 2008
I've come up with a temporary solution until this is fixed. I'm using mod_proxy with the "proxy-sendcl" environment variable running on port 80, proxying to a mod_passenger virtual host running on port 81. I've outlined the problem and solution here: http://www.atnan.com/2008/8/8/transfer-encoding-chunked-chunky-http |
|||||||||||||
,
Feb 10, 2009
Any progress on this? |
|||||||||||||
,
Feb 10, 2009
Sorry I haven't had the chance to look at this yet. Ping me again in the future if it's taking too long. |
|||||||||||||
,
Feb 17, 2009
Having issues with this on CentOS in combination with Apache 2.2.3 Any progress yet? |
|||||||||||||
,
Feb 17, 2009
* ping |
|||||||||||||
,
Mar 05, 2009
Seems to be fixed in newest Passenger release! |
|||||||||||||
,
Mar 24, 2009
I have updated to the latest passenger (2.1.2), but it doesn't seem to be fixed for me: $ curl -vvv -F "query=zoooom" --header "Transfer-Encoding: chunked" http://mysite.local/ * About to connect() to mysite.local port 80 (#0) * Trying 127.0.0.1... connected * Connected to mysite.local (127.0.0.1) port 80 (#0) > POST / HTTP/1.1 > User-Agent: curl/7.18.2 (i386-apple-darwin9.3.0) libcurl/7.18.2 zlib/1.2.3 > Host: mysite.local > Accept: */* > Transfer-Encoding: chunked > Expect: 100-continue > Content-Type: multipart/form-data; boundary=----------------------------5e7066c3b40a > < HTTP/1.1 411 Length Required < Date: Tue, 24 Mar 2009 09:45:25 GMT < Server: Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.7l DAV/2 Phusion_Passenger/2.1.2 < Content-Length: 239 < Connection: close < Content-Type: text/html; charset=iso-8859-1 < <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>411 Length Required</title> </head><body> <h1>Length Required</h1> <p>A request of the requested method POST requires a valid Content-length.<br /> </p> </body></html> * Closing connection #0 |
|||||||||||||
,
Mar 25, 2009
For as long as this line exists, the problem hasn't been fixed and you will need to work around it using mod_proxy: http://github.com/FooBarWidget/passenger/blob/master/ext/apache2/Hooks.cpp#L394 If you're familiar with C++, the fix should be trivial and you should take a look at my patch for inspiration. |
|||||||||||||
,
Apr 01, 2009
This issue has been fixed in commit 5038157db90. The patch was insufficient so I had to do a bunch of other things as well. Sorry for taking so long.
Status: Fixed
Labels: -NeedHelp Milestone-2.1.4 |
|||||||||||||
,
Apr 01, 2009
Thanks Hongli Lai, that's fantastic. |
|||||||||||||
|
|
|||||||||||||