On Tue, Jun 1, 2010 at 10:39 AM, Brian Pane <brianp...@gmail.com> wrote:
> In a filter module I'm writing, it's possible for the first pass
> through the output filter to end up calling:
>    ap_pass_brigade(f->next, an_empty_brigade)
>
> If mod_deflate's output filter appears later in the output filter
> chain, bad things happen:
> 1. On the first trip through the output filter chain, mod_deflate just
> passes the empty brigade through to the next filter:
>    /* Do nothing if asked to filter nothing. */
>    if (APR_BRIGADE_EMPTY(bb)) {
>        return ap_pass_brigade(f->next, bb);
>    }
> 2. Control eventually reaches core_output_filter, which sends the
> response headers.
> 3. On a subsequent trip through the output filter chain, my module calls:
>    ap_pass_brigade(f->next, a non_empty_brigade)
> 4. Upon seeing the non empty brigade, mod_deflate's output filter does
> all the initialization that it would normally do at the start of a
> response.  If the response is compressible, deflate_out_filter adds
> "Content-Encoding: gzip" to the output headers.  The output headers
> have been sent already, though, so the Content-Encoding never gets
> sent.
> 5. The client receives a compressed response without a Content-Encoding 
> header.
>
> I can prevent this by not calling ap_pass_brigade in my module until I
> have the first non-empty brigade for the rest of the output filter
> chain to work with.
>
> I'm curious, though: which module is doing the wrong thing:
> - My module, by sending an empty brigade through the rest of the
> output filter chain prior to sending the first non-empty brigade?
> - Or mod_deflate, by adding fields to the response header after
> calling ap_pass_brigade?

Would it do harm if the core output filter did the same check as
mod_deflate before committing the headers?

Seems like a filter could have just dropped the content of your first
brigade anyway.

-- 
Eric Covener
cove...@gmail.com

Reply via email to