httpd 2.0.55

Failure report:

How it is diagnosed (reproduced or source analysis)?

We did not reproduce the failure, but only rely on source analysis


Apache returns response with incorrect http “Vary” header.

mod_deflate overwrites headers set by applications when serving proxied content.

# wget --header="Accept-Encoding: compress, gzip" -SO backendhtml 2>&1 | grep Vary
4 Vary: Accept

# wget --header="Accept-Encoding: compress, gzip" -SO directhtml 2>&1 | grep Vary
4 Vary: Accept,Accept-Encoding
<-- correct header!

# wget --header="Accept-Encoding: compress, gzip" -SO proxyhtml 2>&1 | grep Vary
 4 Vary: Accept-Encoding

---> The header should be the same as the second one.


FYI> Vary header : Tells downstream proxies how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one from the origin server.

The first one is selecting a response format for a given request. Most REST APIs these days support XML and JSON representations. Some REST servers require clients to send a request parameter indicating the format it chooses to receive, as in

GET /foo/bar?format=json

While this is convenient for testing in browsers or command-line tools like wget or curl, a better way is to rely on server-side negotiation, and sending an Accept header, as in

GET /foo/bar
Accept: application/xml

However, if a server decides to follow this approach, it should also set a Vary header accordingly:

Vary: Accept

This gives caching proxies a chance to cache the responses correctly.

Another scenario is to support compression of responses, particularly useful for transporting large chunks of data. Let’s say, a server supports gzip based compression, and would like to take advantage of it if the server supports it. To start with, the client first sends a Accept-encoding header, as in

GET /foo/bar
Accept-Encoding: gzip

If the server supports gzip compression (which would be another representation of the same resource), it should indicate so, by including a Vary header in the response as in

Vary: Accept-Encoding

and if the server also decides to apply gzip compression to the current response, it should also supply the Content-Encoding header, as in

Vary: Accept-Encoding
Content-Encoding: gzip


Root cause:

mod_deflate should be merging the Vary header, not Setting (overwrite) it.

(The mod_deflate module provides the DEFLATE output filter that allows output from your server to be compressed before being sent to the client over the network.)

static apr_status_t deflate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb){


-        apr_table_setn(r->headers_out, "Vary", "Accept-Encoding");
+        apr_table_mergen(r->headers_out, "Vary", "Accept-Encoding");

mod_deflatek should be *merging* Accept-Encoding into existing Vary response header, but it overwrites previous ones . (apr_table_setn will overwrite while apr_table_mergen will merge (calling strcat).

mod_deflate sends a compressed content if it receives Accept-Encoding header in a request. As a response, it sends Vary response header appending Accept-Encoding to existing other headers.

Therefore, this bug introduces a wrong result (- wrong header)

No any messages!

Can Errlog anticipate the error and put a magic error message?

No. The control-flow is normal, only the data content is messed!