Transfer-Encoding: gzip vs. Content-Encoding: gzip
Solution 1:
Quoting Roy T. Fielding, one of the authors of RFC 2616:
changing content-encoding on the fly in an inconsistent manner (neither "never" nor "always) makes it impossible for later requests regarding that content (e.g., PUT or conditional GET) to be handled correctly. This is, of course, why performing on-the-fly content-encoding is a stupid idea, and why I added Transfer-Encoding to HTTP as the proper way to do on-the-fly encoding without changing the resource.
Source: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31
In other words: Don't do on-the-fly Content-Encoding, use Transfer-Encoding instead!
Edit: That is, unless you want to serve gzipped content to clients that only understand Content-Encoding. Which, unfortunately, seems to be most of them. But be aware that you leave the realms of the spec and might run into issues such as the one mentioned by Fielding as well as others, e.g. when caching proxies are involved.
Solution 2:
The correct usage, as defined in RFC 2616 and actually implemented in the wild, is for the client to send an Accept-Encoding
request header (the client may specify multiple encodings). The server may then, and only then, encode the response according to the client's supported encodings (if the file data is not already stored in that encoding), indicate in the Content-Encoding
response header which encoding is being used. The client can then read data off of the socket based on the Transfer-Encoding
(ie, chunked
) and then decode it based on the Content-Encoding
(ie: gzip
).
So, in your case, the client would send an Accept-Encoding: gzip
request header, and then the server may decide to compress (if not already) and send a Content-Encoding: gzip
and optionally Transfer-Encoding: chunked
response header.
And yes, the Transfer-Encoding
header can be used in requests, but only for HTTP 1.1, which requires that both client and server implementations support the chunked
encoding in both directions.
ETag
uniquely identifies the resource data on the server, not the data actually being transmitted. If a given URL resource changes its ETag
value, it means the server-side data for that resource has changed.