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?

Thanks,
-Brian

Reply via email to