Forum Moderators: phranque
<IfModule mod_headers.c>
<FilesMatch "\.(ico¦gif¦jpg¦png)$">
Header set Cache-Control "max-age=2592000"
</FilesMatch>
<FilesMatch "\.(js¦css)$">
Header set Cache-Control "public,max-age=2592000"
</FilesMatch>
# <FilesMatch "\.(html¦htm¦txt)$">
# Header set Cache-Control "max-age=2700"
# </FilesMatch>
</IfModule>
I then use Page Speed from Google for Firefox / Firebug and
see that it's working - I think. I also used the Chrome
add-on HTTP Headers to view the headers. In this case, it
appears every time that the images are fetched and a 304
return status is issued.
My site is <snip>
Does this all look ok?
David
[edited by: jdMorgan at 6:30 pm (utc) on Dec. 16, 2009]
[edit reason] No URLs, please. See TOS and Charter. [/edit]
You should take advantage of regular expressions, and shorten your third <FileMatch> to
# <FilesMatch "\.(htm[b]l?¦t[/b]xt)$"> You don't strictly need to specify the max-age in the Cache-Control headers, as mod_expires will insert it if you use directives like
ExpiresDefault A2700 Consider that 30 days may be too long for .css and .js caching -- What if you need to update those files? The work-around is to rename them, but that requires editing your pages to change the include links...
I can't comment further without knowing your intended caching policies for each filetype.
Jim
The problem I see in HTTP Headers, as I interpret it, is that
for a given image, there are 2 parts - the first is like a "before"
HTTP get section, and the next is the HTTP request section.
The before part says:
Cache-Control: max-age=0
and the next part says:
Cache-Control: max-age=2592000
and shows the 304 return code.
When I reload the page (not shift-refresh), it says the same thing.
But I would think the "before" part would have max-age=2592000
and I wouldn't see a 304 in my server logs; that is, the image would
be known to be cached in the browser and it wouldn't try to get it.
You can see this on my site using the same tools.
Any input would be appreciated!
David
For the moment, with the code as is, my two main questions are:
* why do I still see 304 return codes in the headers? (and of
course, see those requests in my access log)
* I got conflicting information on using public and private for
the CSS and JS files (or any other files for that matter);
Google Page Speed says to use private, but almost every example
of Cache-Control I've read searching on Google says to use public.
Which is better?
Thanks!
David
--------------------
I'm not sure why you'd want to re-validate images but not pages, and that behavior does not seem to correspond with your cache-control settings... (?)
You should take advantage of regular expressions, and shorten your third <FileMatch> to
# <FilesMatch "\.(html?�txt)$">
You don't strictly need to specify the max-age in the Cache-Control headers, as mod_expires will insert it if you use directives like
ExpiresDefault A2700
within your <FilesMatch> sections.
This also explicitly adds the HTTP "Expires:" header to your server response.
Consider that 30 days may be too long for .css and .js caching -- What if you need to update those files? The work-around is to rename them, but that requires editing your pages to change the include links...
I can't comment further without knowing your intended caching policies for each filetype.
Jim
Unless you're dealing with pages that change on every request, secure pages used for logging into accounts, or ErrorDocuments, then basically everything else should be cacheable. Images and media files the longest, because they're least likely to change, .css and .js in the middle range (not likely to change frequently on a mature site), and pages should be cached for shorter times -- a day or two max, in most cases.
"Public" means to allow caching in public (network) caches, like those used by AOL and Earthlink at the 'borders' of their networks. "Private" means browser and other end-client caches. If you change your content depending on the requesting user agent (e.g. IE versus everyone else), then the benefit of public caching is reduced. But you can still make use of it if you set a proper "Vary: User-agent" header.
Again, I recommend that you use the mod_expires ExpiresDefault directive to set max-age in the Cache-control header. For stuff you want kept current, set 'Cache-control: "no-cache, must-revalidate"'
Here's a working example:
# Set up Cache Control and Expires headers
ExpiresActive On
#
# Default - Set Cache-Control header to expire everything 1 day from last access, set must-revalidate
ExpiresDefault A86400
Header set Cache-Control: "must-revalidate"
#
# Images
<FilesMatch "\.(gif¦jpe?g¦png¦ico)$">
ExpiresDefault A1209600
</FilesMatch>
#
# Web beacon image
<FilesMatch "beacon\.gif$">
ExpiresDefault A0
Header set Cache-Control: "no-store"
</FilesMatch>
#
# Uncacheable files
<FilesMatch "(helpsearch¦localeinfo¦legal_info¦test¦401¦403[a-z]?¦404¦410¦500)\.html$">
ExpiresDefault A0
ErrorHeader set Cache-Control: "no-store"
</FilesMatch>
#
# Very-frequently-updated files
<FilesMatch "^(a-results¦b-results)\.html$">
ExpiresDefault A3600
Header set Cache-Control: "no-cache, must-revalidate"
</FilesMatch>
#
# Admin pages (paswword-protected)
<FilesMatch "^admin_sched\.html$">
Header set Cache-Control: "private, must-revalidate"
</FilesMatch>
#
# Frequently-updated pages
<FilesMatch "^(index¦tech_sched¦calendar¦cal[0-9]{4})\.html$">
ExpiresDefault A7200
Header set Cache-Control: "no-cache, must-revalidate"
</FilesMatch>
Also note that later directives override earlier ones if they have the same or wider scope, and the design shown above relies on this to keep the code short.
Posting on this forum modifies the pipe character, making them show as "¦" broken pipes. If you use any of this code, be sure to change all the pipe characters back to solid ones...
Jim
I can see the gotcha in that, if the browser didn't validate
the image and get the 304, and that image for whatever reason
was deleted on my server in the meantime since it was told to
be cached, then either a broken image results on the page, or
worse, maybe the browser, expecting an image, crashes or otherwise
renders a messed up page.
So maybe the answer here is that even with Cache-Control, browsers
are still going to validate the image and get the 304 code - that
step isn't eliminated. I'd like to think it's possible to get
rid of it, though.
Thanks for the clarification on private and public. I'd just as
soon make all my settings be private then, if it means that cache
occurs on the browser level.
David
The working-example code above (which basically came straight off one of my servers except for being 'anonymized' for posting here), suitably modified for your site's filenames, should stop your problem.
Jim
I tried an example very similar to what you have running.
I have a simple test page on which I keep creating new
copies of an image to test with. I'm still getting 304
messages. Using Live HTTP Headers on Firefox, I am seeing
that my image is marked with the Cache-Control must-revalidate
for the image I'm working with, whence it's causing a 304
to be generated.
This is what I have, with a 5 minute timeout for images so
that I could test 200, 304 and hopefully no logging.
<IfModule mod_expires.c>
ExpiresActive On
# Default - everything 1 day from last access, must-revalidate
ExpiresDefault A86400
Header set Cache-Control: "must-revalidate"
# Images, 5 minutes
<FilesMatch "\.(jpe?g¦gif¦png¦ico)$">
ExpiresDefault A300
</FilesMatch>
</IfModule>
I believe this is working, based on the headers I see.
The keep-alive is 5,99, and I see must-revalidate showing
up where I didn't see it before. Also, I removed the
Cache-Control directives in the .htaccess file in my
docroot, so the code above is the only code in play now.
For that reason, I don't see any Cache-Control info in
the headers for the image.
<snip>
Thanks.
David
[edited by: jdMorgan at 3:58 pm (utc) on Dec. 17, 2009]
[edit reason] No URLs, please. See Terms of Service and Forum Charter. [/edit]
With the <FilesMatch> container order and scope that you have specified, the images are first marked with "must-revalidate" by the unconditional section at the top, and then their expiry time is set by the next section. However, the 'must-revalidate' header is not unset in that image section, so it's still going to be sent with your images.
Directive order is important. Container scope is important. Later code overrides earlier code if both sections have the same scope. Configurations set by earlier code but not modified, countermanded, or replaced by later code remain in force.
I suggest that you explicitly define the filetypes for which revalidation *is* desired, rather than trying to control when it is not. This is the approach taken in my example code.
If however, you wish to continue with your current construct, then you'll need to unset the Cache-Control header within the images <FilesMatch> container:
Header unset Cache-Control
Jim
David