https://issues.apache.org/bugzilla/show_bug.cgi?id=55475
Bug ID: 55475
Summary: mod_proxy breaks HTTP chunked transfer coding
Product: Apache httpd-2
Version: 2.5-HEAD
Hardware: All
OS: All
Status: NEW
Severity: major
Priority: P2
Component: mod_proxy
Assignee: [email protected]
Reporter: [email protected]
Created attachment 30757
--> https://issues.apache.org/bugzilla/attachment.cgi?id=30757&action=edit
A sample backend used for the reproduction steps
Hi,
Apache’s mod_proxy turns incomplete or invalid backend responses into complete
ones if the backend uses the chunked transfer coding. This applies to Apache
2.2.x, 2.4.x and the current trunk (2.5.x). If the zero-length chunk that
terminates a complete chunked-coding message is missing in the backend
response, mod_proxy (or rather the core chunk_filter) adds one. Apache acts as
if the backend server sent a complete response, whereas in fact it didn’t. This
is very worrying because it prevents clients from reliably detecting errors in
the backend.
If the backend doesn’t correctly implement chunked transfer coding, by, say
using illegal characters in the size line that precedes every chunk, those
violations are ignored by mod_proxy, at least in 2.2.25.
The upcoming RFC by the HTTPbis working group clarifies how clients -- and
mod_proxy is a HTTP client -- must handle incomplete messages [1]:
> A client that receives an incomplete response message, which can occur when a
> connection is closed prematurely or when decoding a supposedly chunked
> transfer
> coding fails, must record the message as incomplete.
By turning an incomplete message into a complete one, mod_proxy will be in
violation of this section when the draft becomes standard. But that section
just describes commonly accepted wisdom: detect and report errors, don’t ignore
them, and don’t pretend they didn’t happen.
The situation in 2.4.x and trunk is a little more complicated: there seems to
be some non-determinism. One in ten mod_proxy responses do correctly omit the
terminating zero-length chunk if the backend response didn’t end in one.
Steps to reproduce (assuming wget, bash, Python, pip and Apache already
installed):
$ python -V # should have Python 2.7, not sure if 2.6 works
Python 2.7.5
$ which pip # should have pip, if not see
http://www.pip-installer.org/en/latest/installing.html
/usr/local/bin/pip
$ pip install tornado # or use whatever means you prefer to install pip
$ wget
'https://gist.github.com/hannes-ucsc/a8ce89e3ce7967ffa833/raw/69244d94b1d1dd2f0304ecd428f047fe94eb017a/server.py'
$ python server.py 8881
Meanwhile, in another shell:
$ wget
'https://gist.github.com/hannes-ucsc/32df3a1adf6085bdb2cd/raw/13e55b9fc51e2f4486e9b8f4fde4e84f2bc9221a/httpd.conf'
$ sudo cat httpd.conf > /etc/apache2/httpd.conf # or equivalent
$ apachectl restart
$ curl 'http://localhost/cghub/metadata/analysisObject?fake_error=1' && echo
success || echo failure
Expected:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ResultSet date="2013-08-10 02:09:40" id="43430736">
...
</Result>
curl: (18) transfer closed with outstanding read data remaining
failure
The backend sends an incomplete response, so curl should fail.
Actual:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ResultSet date="2013-08-10 02:09:40" id="43430736">
...
</Result>
success
For Apache 2.4.x and trunk we need to use a loop
$ while ! curl 'http://localhost/cghub/metadata/analysisObject?fake_error=1' ;
do echo retry ; done
Expected: The loop should never exit.
Actual: At some point the loop exits because curl unexpectedly succeeds.
If we hit the backend directly, we get the expected failure:
$ curl 'http://localhost:8881/cghub/metadata/analysisObject?fake_error=1' &&
echo success || echo failure
...
failure
[1] http://www.mnot.net/talks/bits-on-the-wire/httpbis.html#incomplete.messages
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]