Is it safe to use proxy_ignore_headers Vary?
I did some investigation on this subject. I think I found some valuable info on GitHub discussion in Yichun Zhang (author of OpenResty nginx fork) reply:
I'd suggest the following options:
- Cache both compressed and uncompressed responses, and add (a canonicalized) value of the Accept-Encoding to your cache key. So that clients which do not expect gzip'd responses result in a cache miss (and trigger caching the uncompressed version).
- Cache compressed responses and use the standard ngx_gunzip module to uncompress the response body for those clients which do not accept gzip encoding:. See http://nginx.org/en/docs/http/ngx_http_gunzip_module.html But you need to be careful about nginx output filter order (between ngx_srcache's filter and ngx_gunzip's filter).
- Only cache uncompressed content and rely on the ngx_gzip module to compress the data for those clients expecting gzip. Set proxy_set_header Accept-Encoding ''; for example, if the proxy module is used as the content handler.
So, it looks like it isn't safe, and you should cache both (compressed and non-compressed) replies.
But what happens if you receive several requests with the following Accept-Encoding
headers:
Accept-Encoding: gzip
Accept-Encoding: gzip, br
Accept-Encoding: gzip;q=0.8, br;q=0.9
Accept-Encoding: gzip, deflate, br
Does it mean that each of responses will be cached separately? I don't know yet, this needs more extensive testing that I already did. What I'm found so far:
- nginx does not respond to
Accept-Encoding: deflate
with deflated response (which is only a little different from gzipped one). - nginx does not respect the weight qvalue part of header. It will respond with compressed response on request with
Accept-Encoding: identity;q=0.8, gzip;q=0.5
header. If you have angx_brotly
module installed, nginx will always respond with brotly-compressed response if yourAccept-Encoding
request header contains abr
compression method no matter what weights are specified for compression methods.
Yichun Zhang mentions about adding (a canonicalized) value of the Accept-Encoding to your cache key. This can be something like
map $http_accept_encoding $encoding_key {
~[\s:,]br(?:[\s,\;]|$) 2; # brotli
~[\s:,]gzip(?:[\s,\;]|$) 1; # gzip
default 0; # uncompressed
}
If you don't use ngx_brotly
module, things can be simplified:
if ($http_accept_encoding ~ "[\s:,]gzip(?:[\s,;]|$)") {
set $encoding_key 1;
}
After that adding $encoding_key
variable to proxy_cache_key
expression can do the trick, but as I already said, this needs more extensive testing.