httpd-37559

Version:  

httpd 2.0.55

Failure report:

https://issues.apache.org/bugzilla/show_bug.cgi?id=37559

How it is diagnosed (reproduced or source analysis)?

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

Symptom:

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
backend.test.nl/cgi-bin/test.cgi 2>&1 | grep Vary
4 Vary: Accept

# wget --header="Accept-Encoding: compress, gzip" -SO directhtml  
direct.test.nl/cgi-bin/test.cgi 2>&1 | grep Vary
4 Vary: Accept,Accept-Encoding
<-- correct header!

# wget --header="Accept-Encoding: compress, gzip" -SO proxyhtml  
proxy.test.nl/cgi-bin/test.cgi 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!