I want to set cache-headers using the mod_expires module from apache. My configuration looks somewhat like this:
<LocationMatch ^/static >
ExpiresDefault "access plus 1 years"
</LocationMatch>
The problem is, that the files are generated by a third system I don't control. These system provides files with the following headers:
Date Mon, 24 Oct 2011 08:39:02 GMT
Cache-Control no-cache,no-store,must-revalidate
Pragma no-cache
Expires Thu, 01 Dec 1994 16:00:00 GMT
These headers makes it impossible to set the cache-headers with mod_expires. http://httpd.apache.org/docs/2.2/mod/mod_expires.html tells us why:
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.
Is there any possible way to circumvent this rule and overwrite the headers with mod_expires?
Update:
One possible solution, to avoid this limitation is to use only mod_headers to set the cache-headers. Unfortunately, this isn't an alternative because the values have to be calculated.
Thanks it advance.
Unfortunately, it's a known limitation and we had to fall back to use only mod_headers.
Regilero's suggestion won't work because header directives will be processed very late in the response processing - after mod_expire directive. So you'd unset the headers after mod_expires did (or didn't) what it was supposed to do.
If it's apache 2.2 you could try putting early at the end of each header directive. That will tell it to do this in an early stage of response processing as opposed to at the end.
so try:
<LocationMatch ^/static >
Header unset Cache-Control early
Header unset Pragma early
Header unset Expires early
ExpiresDefault "access plus 1 years"
</LocationMatch>
Haven't tested tho, but give it a try...
Have you tried mixing it with mod_headers?
<LocationMatch ^/static >
Header unset Cache-Control
Header unset Pragma
Header unset Expires
ExpiresDefault "access plus 1 years"
</LocationMatch>
Not tested, but in case of...
Related
I am getting Expire Header as Thu, 19 Nov 1981 08:52:00 GMT on my webpage how i can remove expire header using apache.
Thanks
Thanigaivelan
In your .htacess:
ExpiresActive Off
It is not good to disable this complete.
Also take a look at mod_expires.
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.
These HTTP headers are an instruction to the client about the
document's validity and persistence. If cached, the document may be
fetched from the cache rather than from the source until this time has
passed. After that, the cache copy is considered "expired" and
invalid, and a new copy must be obtained from the source.
To modify Cache-Control directives other than max-age (see RFC 2616
section 14.9), you can use the Header directive.
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.
ExpiresByType text/html "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"
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.
I have a handful of directories with content which will never change.
Is it possible to create .htaccess file which tells the browser that anything in this directory and sub- directories can be cached for a very long time?
I would like to copy the same .htaccess file in each directory if possible.
If this is possible would you recommend max-age over expires or both?
So it does look possible.... the .htaccess file syntax is:
Header unset Last-Modified
FileETag none
ExpiresActive On
ExpiresDefault "access plus 1 years"
This will turn off Etags and turn on cache-control: max-age
Then put this .htaccess file in the directory and all files (including it's sub-directories will be cached for 1 year.
I decided to put all my cache-able content under a single root directory and edit the httpd.conf as
<Directory "C:\somedir\cache">
Header unset Last-Modified
FileETag none
ExpiresActive On
ExpiresDefault "access plus 1 years"
</Directory>
I am still in the process of testing this. I just hope this does not turn off Etags for the rest of the site. So far it looks like it's working as planned.
UPDATE (after 6 months):
Setting the ExpiresDefault and allowing e-tags is the best thing to do.
in httpd.conf:
<Directory "C:\somedir\cache">
ExpiresActive On
ExpiresDefault "access plus 1 year"
</Directory>
Make sure "somedir" is inside of the apache root (such as htdocs).
Allowing e-tags is a good because after 1 year, the browser will re-validate the file by passing the e-tag. The web server will send back a 304 - Not Modified and reset the max-age to 1 year. This is very efficient.
All in all, you can watch the apache log file and see that items in /cache dir are begin served once.
Note: I have found that setting Header append Cache-Control "public" is ok to do if you want.
Final Version:
Here's the final version: (just add this at the bottom of the httd.conf)
<Directory "C:\somedir\cache">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header append Cache-Control "public"
</Directory>
Inspecting the header should reveal this:
Accept-Ranges:bytes
Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Content-Language:en
Content-Length:746
Content-Type:text/css
Date:Thu, 29 May 2014 15:23:50 GMT
ETag:"240000000add63-2ea-4f4086d72ad01"
Expires:Fri, 29 May 2015 15:23:50 GMT
Keep-Alive:timeout=40, max=200
Last-Modified:Fri, 07 Mar 2014 18:28:59 GMT
This will:
Set the max-age for 1 year (the longest recommended)
Send the expires tag of 1 year
Send an Etag, so after 1 year the browser will perform etag validation
Let intermediate caching devices/services know that they can cache the file for 1 year.
FYI, if you do what is mentioned above and your Apache won't restart then you may be getting this error:
The Apache service named reported the following error:
>>> Invalid command 'ExpiresActive', perhaps misspelled or defined by a module not included in the server configuration.
You can find that error by clicking "Start", type in "Computer Management", launch it, in the tree open "Event Viewer -> Windows Logs -> Application". That's where I found the error above.
Easy fix, just uncomment this line in httpd.conf:
#LoadModule expires_module modules/mod_expires.so
If I do this:
<IfModule mod_expires.c>
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4|css|js|php)$">
ExpiresActive On
ExpiresDefault "access plus 30 days"
</FilesMatch>
</IfModule>
It doesn't set properly the Expire header, whereas if I "force" it by hand like this:
<IfModule mod_expires.c>
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4|css|js|php)$">
ExpiresActive On
Header set Expires "Thu, 18 Jan 2012 20:00:00 GMT"
</FilesMatch>
</IfModule>
It works. This implies 2 things:
mod_expire is installed (IfModule mod_expires.c is true)
the Expire header is not modified after this rule is applied.
What am I missing?
By the way: if you have any solution to make it work I'm your man!
Ok I've got it from the official documentation here:
Note that if you use a modification date based setting, the Expires
header will not be added to content that does not come from a file on
disk. This is due to the fact that there is no modification time for
such content.
So it works only for static files, and not for all the other ones: they're not static.
This one got me stumped as well because AFAIK, it should work so I tried it on a test VM varying the N days and refreshing. Works fine for me. My Apache version is
Server version: Apache/2.2.14 (Ubuntu)
Server built: Nov 18 2010 21:17:19
Any the headers for a test file (using chrome developer tools) (with N=15) show:
Date:Mon, 09 Jan 2012 01:48:43 GMT
ETag:"7574-5-4b60e88a820a1"
Expires:Tue, 24 Jan 2012 01:48:43 GMT
My thought is that any ExpiresDefault can be overridden by a Header set Expires. Have you grepped the .htaccess hierarchy to make sure that your ExpiresDefault isn't being overridden at a lower level.
If you don't want htaccess files doing this you need to disable them in your http config.
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.