############################
# FILES - CACHING: CONTROL #
############################
Header set Cache-Control "max-age=2592000, public"
<FilesMatch "\.(?:bmp|css|cur|gif|ico|jp(?:eg?|g)|js|png|svgz?|tiff?|webp)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
<FilesMatch "\.(?:html?|json|php|xml)$">
Header set Cache-Control "max-age=0, must-revalidate, no-cache, no-store, post-check=0, pre-check=0, private"
</FilesMatch>
<FilesMatch "\.(?:atom|rdf|rss)$">
Header set Cache-Control "max-age=3600, public"
</FilesMatch>
Header merge Cache-Control "no-transform"
This is a snippet of my htacces
in which I handle the Cache-Control
header. By default, for all the files, it is set to max-age=2592000, public
.
On the bottom I'm always trying to append a no-transform
directive but it simply doesn't work. It... well it just does nothing. The no-transform
directive is never been set. I tried replacing merge
with append
, nothing changes.
Now, this is what I noticed. If I replace the third FilesMatch
directive with:
<FilesMatch "\.(?:atom|rdf|rss)$">
Header set Cache-Control "max-age=3600, public"
Header merge Cache-Control "no-transform"
</FilesMatch>
It works. Every feed file of my site will have the no-transform
directive. If I change the last line of my first snippet to:
<FilesMatch "^.+$">
Header merge Cache-Control "no-transform"
</FilesMatch>
Well... it works for all the files. Just... WHY?!
I also noticed another very strange behavior concerning headers. Let's say I want to force a keep-alive on connections. I insert this somewhere inside my htaccess file:
Header merge Connection "Keep-Alive"
And this is what I get in my response header:
Connection: Keep-Alive, Keep-Alive
Again... WHY?!
I suspect (though can't find any documentation to back this up as it's not 100% clear from this page: https://httpd.apache.org/docs/2.4/sections.html), that FilesMatch directives are processed after directives which are not in FileMatch.
Therefore even though you write this:
Header set Cache-Control "max-age=2592000, public"
<FilesMatch "\.(?:atom|rdf|rss)$">
Header set Cache-Control "max-age=3600, public"
</FilesMatch>
Header merge Cache-Control "no-transform"
Apache processes it like this:
Header set Cache-Control "max-age=2592000, public"
Header merge Cache-Control "no-transform"
<FilesMatch "\.(?:atom|rdf|rss)$">
Header set Cache-Control "max-age=3600, public"
</FilesMatch>
Which means the "later" set overrides the earlier merge. If you change the "set" in your FilesMatch pieces to "merge" you should see it work as it will no longer override it.
Though to be honest I think this way of writing you config is very difficult to follow. Since you are setting you cache control header four times why not just set the no-transform at the same time in each of the four set directives? Yes it's a tiny bit of repetition but a lot clearer and means you won't run into these order problems!
Your second issue is easier to explain from the documentation: http://httpd.apache.org/docs/current/mod/mod_headers.html#header:
merge ... Values in double quotes are considered different from otherwise identical unquoted values
So if value is Keep-Alive and you add "Keep-Alive" then you end up with "Keep-Alive Keep-Alive".
Btw as an aside you should not try to enable Keep-Alives just by setting the header. While that will work for the client, Apache needs to also keep the connection alive for the client to connect to, which it won't just by setting this header. So the client will think the connection is being kept alive but in fact it won't be as the server will close the connection anyway. You need to set it with the config like the following (which will also set the necessary headers for you):
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5