I'm trying to control the caching of files within a certain directory. I want the default cache time to be 15 minutes, but I want to let the application change it if necessary. For example, I may have a PHP script that I want to refresh every 1 minute, so I'll set the cache-control headers within PHP for that script. But for all of the other files I just want the cache time to be 15 minutes, and some of those are static files, so I can't just set a default cache-time in PHP.
I currently have this in my Apache config:
<Directory />
Options FollowSymLinks
AllowOverride None
Header set Cache-Control "max-age=900"
</Directory>
This works great for 99% of the cases, where I just want a 15 minute cache. However, if my PHP script sets a cache-control header, then this setting will overwrite it.
I've looked at the documentation for mod_header and none of the settings (unset, add, append, etc.) seem to give me what I need.
Thanks in advance.
Take a look at mod_expires instead http://httpd.apache.org/docs/2.2/mod/mod_expires.html. The docs say that it won't overwrite headers created by your PHP script:
"When the Expires header is already part of the response generated by
the server, for example when generated by a CGI script or proxied from
an origin server, this module does not change or add an Expires or
Cache-Control header."
Here is an example config for mod_expires:
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault A600
ExpiresByType image/gif "access plus 1 day"
ExpiresByType image/jpeg "access plus 1 day"
ExpiresByType image/png "access plus 1 day"
ExpiresByType image/x-icon "access plus 1 day"
<FilesMatch "\.(php|php4)$">
ExpiresByType text/html "now"
</FilesMatch>
</IfModule>
Taken from http://howto.gumph.org/content/reduce-webserver-bandwidth/
Good luck!
According to php manual
<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
?>
By sending the headers above, you should override any settings that may otherwise cause the output of your script to be cached.
Related
Setup
Debian GNU/Linux 7.6 (wheezy) will full access to Apache and virtual
host files.
Concrete5 CMS: http://www.concrete5.org/
Problem
Our website is sending Pragma: no-cache in headers which is stopping a number of optimisations from working - including the CloudFlare service: https://www.cloudflare.com/
Solutions which didn't work
When researching, we either didn't understand the answers or they seemed to be for specific use cases (like Oracle or php frameworks we're not using) but we did try the following:
1. Force caching via the site's .htaccess:
<FilesMatch "\.(ico|jpeg|png|gif|js|css)$">
Header unset Cache-Control
Header unset Pragma
</FilesMatch>
2. Force caching via Concrete5's header.php file
header("Cache-Control: max-age=2592000"); //30days (60sec * 60min * 24hours * 30days)
3. Search site's root for no-cache using grep
$ grep -r "no-cache" * .
backup/databasebackup.php:header('Cache-Control: no-cache, must-revalidate');
concrete/core/controllers/single_pages/login.php: header("Cache-Control: no-store, no-cache, must-revalidate");
concrete/core/controllers/single_pages/login.php: header("Pragma: no-cache");
concrete/js/tiny_mce/plugins/spellchecker/rpc.php:header("Cache-Control: no-store, no-cache, must-revalidate");
concrete/js/tiny_mce/plugins/spellchecker/rpc.php: header("Pragma: no-cache");
concrete/libraries/3rdparty/securimage/securimage.php: header('Cache-Control: no-store, no-cache, must-revalidate');
concrete/libraries/3rdparty/securimage/securimage.php: header("Cache-Control: no-store, no-cache, must-revalidate");
concrete/libraries/3rdparty/securimage/securimage.php: header("Pragma: no-cache");
But after looking at the files/scripts Concrete5 is setting no-cache on (login, database backups, text editor configs etc), we kind of understand why - plus these seem to be for specific files, not the entire site right?
4. Make a blank php file, request it and check the header
The blank file was served with caching on so we suspect that php is the culprit - but have no idea how to isolate the cause sorry.
Question
How do we troubleshoot and fix this issue?
Skill level
We do front-end design and understand the basics on how to setup and serve a CMS but don't have much experience with server configuration or troubleshooting cache issues.
We have command line access to the server and pretty much have full access to Debian, Apache, and the site's install.
Any help would be much appreciated.
Cheers
Ben
Update
To add max-age in a PHP script:
header("Cache-Control: max-age=xxxx");
Where xxxx is the number of seconds to cache, zero for no cache.
OR
If you configure by Content-Type (MIME Type)
header('Content-Type: text/html; charset=utf-8');
Header Set Cache-Control "max-age=0, no-store"
to configure cache by Content-Type (MIME Type):
In .htaccess ot httpd.conf
ExpiresByType text/html "access plus 30 day"
ExpiresByType text/css "access plus 30 day"
ExpiresByType text/javascript "access plus 30 day"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
If these methods are not working you need to majke sure the modules are loaded.
You need access to httpd.conf
LoadModule expires_module libexec/mod_expires.so
LoadModule headers_module libexec/mod_headers.so
AddModule mod_expires.c
AddModule mod_headers.c
...
AddModule mod_gzip.c
Note that the load order is important in Apache/1.3x, mod_gzip must load last, after all other modules.
For Apache/2.0:
LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so
end of Update
You should add the same cache based on MIME Type as well as (or rather than) file extension.
The cache should be max-age.
The W3C says max-age takes precedence over all other cache headers.
To troubleshoot you are doing well already if you are not getting "Internal Server Error 500"
In FireFox or Chrome
Right Click page
Select Inspect Element
Go to the "Network Tab"
Change Type from "All" to "HTML"
Click on the HTML page in the list
You should be able to see exactly what is in the HTTP Response Header.
FireFox
Chrome
Finally got to the bottom of this, some of the Concrete5 Blocks on pages are stopping the pages from being cached.
If we turn on "Force full page caching" then we see some weird behaviour because the functionality is frozen by the cache, so we've had to turn it off.
Essentially, we can't cache the site fully because of the functionality in blocks on the page. We can only use APC caching.
I am working on a website and I've got 1 php file which I want to cache longer than the rest (1 year instead of 15 min). For the general cache settings I used a .htaccess file but is it possible to do this in htacces? Or do I have to do it in a different way?
You could put this .htaccess in the directory where there is your PHP file, but others files in this directory will be affected.
## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/x-javascript "access 1 year"
ExpiresDefault "access 1 year"
</IfModule>
## EXPIRES CACHING ##
This module controls the setting of the Expires HTTP header and the max-age directive of the Cache-Control HTTP header in server responses. The expiration date can set to be relative to either the time the source file was last modified, or to the time of the client access.
Depends on what you want to do. See here for more informations.
When I specify:
header('Cache-Control: max-age=31557600');
the result header is
Cache-Control: max-age=31557600, max-age=0
It seems to still work, but it seems what php is doing is combining my Cache-Control header with what it sends if I don't specify the header.
Is there a way to nuke the second max-age=0 in php?
The culprit was mod_expires
When mod_expires is active, and the line
ExpiresDefault A0
is present, it will put max-age=0 on anything that doesn't match one of its ExpiresByType directives.
So if using a php wrapper for something you want browsers to cache, don't set ExpiresDefault to anything and make sure there is not an ExpiresByType set for the same mime type.
I want to cache all of my files but I can't figure out how to get it to work so that the tests approve. I have currently
<meta http-equiv="Cache-Control" content="private" />
<meta http-equiv="Expires" content="86400000" />
<meta http-equiv="Cache-Control" content="max-age=86400000" />
The last line I added just to test if having expires and max-age will help (it doesn't)
I was using http://www.webpagetest.org/, https://developers.google.com/pagespeed/#, and http://gtmetrix.com/
can anyone tell me simply how to make sure everything is cached privately? I have checked a bunch of other pages but no one gives legit HTML code. Please list actual code don't just tell me to use Cache-Control and expires and that like every other website I have seen uses. I really need example code in order to understand. Thank you for any help in advance. I am also using PHP so if doing it in a header() then that would work too.
Thank you very much
edit: I also tried using .htaccess in order to do it but that didn't work. I don't know if it was a setting with my server or what but it didn't change anything with the test.
When you specify an expiration time in an HTML document, it only applies to the actual document.
Assuming you have an Apache webserver with mod_expires enabled, you can create a file named .htaccess and include the following
ExpiresActive On
ExpiresByType image/gif 86400000
ExpiresByType image/png 86400000
ExpiresByType image/jpg 86400000
ExpiresByType image/jpeg 86400000
ExpiresByType text/html 86400000
ExpiresByType text/javascript 86400000
ExpiresByType text/plain 86400000
you can use .htaccess to cache your files.
#cache html and htm files for one day
<FilesMatch ".(html|htm)$">
Header set Cache-Control "max-age=43200"
</FilesMatch>
#cache css, javascript and text files for one week
<FilesMatch ".(js|css|txt)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
#cache flash and images for one month
<FilesMatch ".(flv|swf|ico|gif|jpg|jpeg|png)$">
Header set Cache-Control "max-age=2592000"
</FilesMatch>
#disable cache for script files
<FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
Header unset Cache-Control
</FilesMatch>
I was checking google page speed tool # http://pagespeed.googlelabs.com and my site point was 88. It suggest me to use Leverage browser caching for the site. I searched stackoverflow about it but all it was about htaccess, my hosting doesn't let me to use htaccess, how can I make it in PHP without htaccess?
htaccess codes were
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=290304000, public"
</FilesMatch>
If your hoster does not support .htaccess nor configuring the webserver with other methods, you would need to implement the whole HTTP stack into your own application to offer configuration of your own.
That means sending the appropriate headers for the files in question next to the files itself. You would need to map those files onto commands your application (which is normally done with .htaccess + Mod_Rewrite as well).
Shortly said, you would need to deliver everything by PHP scripts that set the headers in question. However this has the downside that PHP needs to process everything which will have a drawback on speed compared to static file delivery by the webserver. So I can not really suggest you to do it that way. It's much easier to just get a proper webhoster (or to upgrade your package) to get the features you're looking for before re-inventing the wheel. So getting some .htaccess support is probably the most easy way.
As an alternative but somewhat similiar, you can consider to put the static files onto another host that provides the features you need (e.g. a CDN) and leave the core application on the current webhost, but I assume this only makes things more complicated than it does help you easily.
After doing a day of research i get this solution for Leverage browser cashing with .htaccess file.
Remember mod_expires and mod_headers should be open in server
Just put the on the .htaccess file.
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 seconds"
ExpiresByType image/x-icon "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType text/javascript "access plus 216000 seconds"
ExpiresByType application/x-javascript "access plus 216000 seconds"
ExpiresByType text/html "access plus 600 seconds"
ExpiresByType application/xhtml+xml "access plus 600 seconds"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\\.(ico|jpe?g|png|gif|swf)$">
Header set Cache-Control "max-age=2692000, public"
</FilesMatch>
<FilesMatch "\\.(css)$">
Header set Cache-Control "max-age=2692000, public"
</FilesMatch>
<FilesMatch "\\.(js)$">
Header set Cache-Control "max-age=216000, private"
</FilesMatch>
<FilesMatch "\\.(x?html?|php)$">
Header set Cache-Control "max-age=600, private, must-revalidate"
</FilesMatch>
Header unset ETag
Header unset Last-Modified
</IfModule>
you can't do it without permissions to do anything via htaccess or ACP