I have a .htaccess file that handles the browser caching. I set the rules with file extensions. How can I modify the following snippet to exclude a specific directory from the browser caching?
<FilesMatch "\.(gif|png|jpg|js|css|ico|woff|eot|svg|ttf)$">
Header set Cache-Control "max-age=2592000, public, must-revalidate"
Header unset Last-Modified
</FilesMatch>
I there any way to totally forbid the caching in this directory?
You can try to overwrite parent cache function. Just replace another htaccess file under desired folder and set to cache for 1 sec. Worked for me.
ExpiresActive On
ExpiresDefault A1
Header append Cache-Control must-revalidate
Related
############################
# 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
In Apache, how can I set a Response Header only if it is not already set by the CGI application?
I need a way to automatically add the Cache-Control header to static content on my website, but I want the CGI application to be able to specify its own Cache-Control header too.
SetEnvIf will not work for this purpose because it only matches Request Headers.
Is there some way to conditionally / optionally set a header if it is not already set?
1) Configure Apache to append the value of empty string ("") to the Cache-Control header to ensure the header is always included in the response.
2) Configure Apache to set the Cache-Control header only if it's still set to empty string.
<FilesMatch "\.(css|ico|flv|gif|jpeg|jpg|js|pdf|png|swf)$">
Header append Cache-Control ""
Header edit Cache-Control "^[, ]*$" "max-age=1800, public"
</FilesMatch>
The code below used to be Ok. But now I found that browsers do not cache .php files. Why? MY site is on share host. The host never reply. All the other extention files such as html, js, css, png, are fine cached, besides .php.
Header unset Pragma
FileETag None
Header unset ETag
# 1 YEAR
<filesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4)$">
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2015 20:00:00 GMT"
Header unset Last-Modified
</filesMatch>
# 2 HOURS
<filesMatch ".(html|htm|xml|txt|xsl|php)$">
Header set Cache-Control "max-age=7200, public"
</filesMatch>
<filesMatch ".(js|css)$">
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2014 20:00:00 GMT"
Header unset Last-Modified
</filesMatch>
Because PHP files can generate different output each time they run, servers don't send cache commands for the output: it might be different next time.
You can force caching by including Cache-control headers in the output generated by PHP, or by specifying the ContentType header from your PHP script.
Which of these is a better approach depends on what your script is doing. Either way, you can implement fine control over caching if your aplication requires it.
Apache is sending Cache-Control headers for 3## status codes, like 302 redirects. This is causing Firefox (possibly starting with Firefox 5) to cache the 302 redirects--which results in an infinite redirect loop for some of my pages.
Here are the settings that I am using in my httpd.conf:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault A600
</IfModule>
If I remove the ExpiresDefault setting, the problem goes away, so I am confident that this is the exact setting that is causing the problem. If I change ExpiresDefault A600 to ExpiresByType text/html A600 the problem is still there.
I'd like to have browsers cache my content by default, but this is a deal-breaker.
Are there any settings I can use to tell Apache to send a different Cache-Control header for 3## status codes?
If you add the Cache-Control headers in your application, which builds the redirect, apache will not overwrite it.
Cache-Control: max-age=0
Expires: Sat, 04 Feb 2012 07:02:38 GMT
if you use apaches mod_rewrite to do the redirect you could add the headers with the
mod_headers module.
Despite various measure ments to setup correct caching code in htaccess file, I still get this error:
Specify a cache validator:
All static resources should have either a Last-Modified or ETag header. This will allow browsers to take advantage of the full benefits of caching.
Is there anything wrong with my htaccess caching settings? If you have improvements for these settings i will be very happy to hear. Thank you very much for your suggestions.
<IfModule mod_headers.c>
Header unset Pragma
FileETag None
Header unset ETag
ExpiresActive On
##### DYNAMIC PAGES
<FilesMatch "\\.(ast|php|css)$">
Header set Cache-Control "public, max-age=3600, must-revalidate"
</FilesMatch>
##### STATIC FILES
<FilesMatch "\\.(png|svg|swf|js|xml)$">
Header set Cache-Control "public, max-age=604800, must-revalidate"
Header unset Last-Modified
</FilesMatch>
##### ETERNAL FILES
<FilesMatch "\\.(ico|jpg|gif|ttf|eot|pdf|flv)$">
Header set Cache-Control "public, max-age=7257600, must-revalidate"
Header unset Last-Modified
</FilesMatch>
</IfModule>
You are specifically unsetting the Last-Modified header. That's the cache validator section. Remove those lines that include:
Header unset Last-Modified
Also, is your css really dynamic? CSS can be huge for a lot of websites. Try to cache that just like any other static content.
All static resources should have either a Last-Modified or ETag header. This will allow browsers to take advantage of the full benefits of caching.