Re: [PATCH] mod_deflate + mod_proxy bug

2004-06-10 Thread Joe Orton
On Wed, Jun 09, 2004 at 05:23:38PM -0400, Allan Edwards wrote:
 Running ProxyPass with mod_deflate results in
 an extraneous 20 bytes being tacked onto 304
 responses from the backend.
 
 The problem is that mod_deflate doesn't handle
 the zero byte body, adds the gzip header and
 tries to compress 0 bytes.
 
 This patch detects the fact that there was no
 data to compress and removes the gzip header
 from the bucket brigade.

Wouldn't it be simpler to just check for a brigade containing just EOS
and do nothing for that case in the first place?

But the fact that the proxy passes such a brigade through the output
filters in the first place sounds like the real bug, it doesn't happen
for a non-proxied 304 response.

joe


Re: [PATCH] mod_deflate + mod_proxy bug

2004-06-10 Thread Nick Kew
On Wed, 9 Jun 2004, Allan Edwards wrote:

 Running ProxyPass with mod_deflate results in
 an extraneous 20 bytes being tacked onto 304
 responses from the backend.

 The problem is that mod_deflate doesn't handle
 the zero byte body, adds the gzip header and
 tries to compress 0 bytes.

 This patch detects the fact that there was no
 data to compress and removes the gzip header
 from the bucket brigade.

 Any comments before I commit to head?

This is part of a slightly broader problem with proxying and mod_deflate:
it'll also waste time gzipping already-compressed data from the backend
in those cases where the compression is not explicitly indicated in the
Content-Encoding header.  Obvious examples are all the main image formats.

I'm currently running a hack that works around this, and planning a
better review when time permits (i.e. when I've caught up with things
after http://www.theatreroyal.com/showpage.php?dd=1theid=2578
which now has three nights left to run).

More interesting is the entire subject of filtering in a dynamic
context such as a proxy.  The directives available to control filtering
are simply not up to it.  Watch this space:-)

-- 
Nick Kew


Re: [PATCH] mod_deflate + mod_proxy bug

2004-06-10 Thread Allan Edwards
Joe Orton wrote:
Wouldn't it be simpler to just check for a brigade containing just EOS
and do nothing for that case in the first place?
Yes I had considered that. The initial patch covered some pathological
cases but after having looked over the code some more I think the simpler
more efficient way of bailing on just EOS is sufficient.
But the fact that the proxy passes such a brigade through the output
filters in the first place sounds like the real bug, it doesn't happen
for a non-proxied 304 response.
Whether or not this is a bug I guess is open for debate. What happens
for non proxied error responses is that ap_send_error_response resets
r-output_flters to r-proto_output_filters so the deflate filter is
taken out of the respone path. In the proxy path there is no such logic
for error responses, so error pages would get zipped. But I don't know
that this violates the RFC and browsers seem to be able to handle it.
Allan


[PATCH] mod_deflate + mod_proxy bug

2004-06-09 Thread Allan Edwards
Running ProxyPass with mod_deflate results in
an extraneous 20 bytes being tacked onto 304
responses from the backend.
The problem is that mod_deflate doesn't handle
the zero byte body, adds the gzip header and
tries to compress 0 bytes.
This patch detects the fact that there was no
data to compress and removes the gzip header
from the bucket brigade.
Any comments before I commit to head?
Allan
--
Index: mod_deflate.c
===
RCS file: /home/cvs/httpd-2.0/modules/filters/mod_deflate.c,v
retrieving revision 1.49
diff -u -d -b -r1.49 mod_deflate.c
--- mod_deflate.c   1 Jun 2004 13:06:10 -   1.49
+++ mod_deflate.c   9 Jun 2004 16:38:30 -
@@ -433,6 +433,8 @@
 char *buf;
 unsigned int deflate_len;
+if (ctx-stream.total_in != 0) {
+
 ctx-stream.avail_in = 0; /* should be zero already anyway */
 for (;;) {
 deflate_len = c-bufferSize - ctx-stream.avail_out;
@@ -510,6 +512,14 @@
  * Time to pass it along down the chain.
  */
 return ap_pass_brigade(f-next, ctx-bb);
+}
+else {
+/* this was a zero length response, remove gzip header bucket then 
pass down the EOS */
+APR_BUCKET_REMOVE(APR_BRIGADE_FIRST(ctx-bb));
+APR_BUCKET_REMOVE(e);
+APR_BRIGADE_INSERT_TAIL(ctx-bb, e);
+return ap_pass_brigade(f-next, ctx-bb);
+}
 }
 if (APR_BUCKET_IS_FLUSH(e)) {



Re: [PATCH] mod_deflate + mod_proxy bug

2004-06-09 Thread Cliff Woolley
On Wed, 9 Jun 2004, Allan Edwards wrote:

 +}
 +else {
 +/* this was a zero length response, remove gzip header bucket then 
 pass down the EOS */
 +APR_BUCKET_REMOVE(APR_BRIGADE_FIRST(ctx-bb));
 +APR_BUCKET_REMOVE(e);
 +APR_BRIGADE_INSERT_TAIL(ctx-bb, e);
 +return ap_pass_brigade(f-next, ctx-bb);
 +}

I haven't looked at the entire context of this, but if you remove a bucket
(brigade_first(ctx-bb) from a brigade without deleting it and without
having any extra pointers to it, you'll leak memory.

Also, what happens if e *is* the first bucket in the brigade?  Can that
occur?  I think that by coincidence given the implementation of
APR_BUCKET_REMOVE, nothing bad would happen by double-removing a given
bucket twice in a row, but in general that seems like a bad idea and
should be avoided.

--Cliff


Re: [PATCH] mod_deflate + mod_proxy bug

2004-06-09 Thread Allan Edwards
Cliff Woolley wrote:
I haven't looked at the entire context of this, but if you remove a bucket
(brigade_first(ctx-bb) from a brigade without deleting it and without
having any extra pointers to it, you'll leak memory.
Thanks for catching that! I'll replace APR_BUCKET_REMOVE with
a call to apr_bucket_delete(). Also just realized I need to add
a call to deflateEnd().
Also, what happens if e *is* the first bucket in the brigade?  Can that
occur?  I think that by coincidence given the implementation of
APR_BUCKET_REMOVE, nothing bad would happen by double-removing a given
bucket twice in a row, but in general that seems like a bad idea and
should be avoided.
e is on the brigade passed into deflate_out_filter and the gzip
header bucket is in ctx-bb so that is not a problem.
Thanks, Allan



Re: [PATCH] mod_deflate + mod_proxy bug

2004-06-09 Thread Cliff Woolley
On Wed, 9 Jun 2004, Allan Edwards wrote:

 Also just realized I need to add a call to deflateEnd().

Oh right, that too.  :-)

 e is on the brigade passed into deflate_out_filter and the gzip
 header bucket is in ctx-bb so that is not a problem.

Ah, yeah, that would make sense.  Cool.