I'd like to set the Expires header for js.gz files. I've added a .htaccess file to the directory containing these files. This is actually part of a widget I'm developing which I will be deployed across multiple domains, so I don't want to use any apache modules which might be inaccessible to my clients.
Header set Expires "Tue, 16 Jun 2020 20:00:00 GMT"
not with mod_expires
ExpiresActive On
I want to dynamically set the date to today's date plus 1 month.
Resolved in comments! Thanks fge
Uh, why not mod_expire?? It is designed for this job – fge
Related
I have the following code in my .htaccess file:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
</IfModule>
This means that jpg and jpeg images should have a cache expiration date of 1 year. The response headers in Chrome's DevTools Console reflect that.
content-type:image/jpeg
date:Mon, 07 Nov 2016 04:05:46 GMT
expires:Tue, 07 Nov 2017 04:05:46 GMT
last-modified:Sun, 06 Nov 2016 18:40:41 GMT
However, on PageSpeed insights, the recommendations show that the cache is only valid for 5 hours and I should increase that time. Why is that?
You should use the newer Cache-Control header:
Cache-Control: max-age=<some-time-in-seconds>, public
The old HTTP/1 Expires header is imprecise and causes problems when intermediate caches are involved.
Google PageSpeed probably assumes that it will not be respected by browsers. In that case the browser reverts to so called heuristic caching where the expiration is typically calculated as a fraction (e.g. 20%) of the difference between the Last-Modified date and now - which would yield a value similar to the one you saw.
I can't get my mind wrapped around the comments and way of coding, to set a header only for .html in for example the .htaccess file in html5 boilerplate.
The clue for a big codeblock lays in the fact that 'mod_headers can't match on the content type' (as # commented). So I wander 1: why is there a 'Header unset' in a <FilesMatch>, that just has been announced to be impossible?
<IfModule mod_headers.c>
Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
# `mod_headers` cannot match based on the content-type, however,
# the `Content-Security-Policy` response header should be send
# only for HTML documents and not for the other resources.
<FilesMatch "\.(appcache|atom|bbaw|bmp|crx|css|cur|eot|f4[abpv]|flv|geojson|gif|htc|ico|jpe?g|js|json(ld)?|m4[av]|manifest|map|mp4|oex|og[agv]|opus|otf|pdf|png|rdf|rss|safariextz|svgz?|swf|topojson|tt[cf]|txt|vcard|vcf|vtt|webapp|web[mp]|woff2?|xloc|xml|xpi)$">
Header unset Content-Security-Policy
</FilesMatch>
</IfModule>
I looked everywhere, but only land on pages that have the same, almost ritual used codeblock, without further explanation. So question 2: why is a simple declaration like this not possible?:
<IfModule mod_headers.c>
# Content-Security-Policy for .html files
<FilesMatch "\.(html)$">
Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
</FilesMatch>
# OR like this
<Files ~ "\.(html)$">
Header set Cache-Control "public, must-revalidate"
</Files>
</IfModule>
It is possible to do that as per your second example. But .html are not the only files that could be sent as documents. You could also use .php or .htm or any other number of files. Some of these (like .php) may execute and then ultimately return HTML but the server doesn't know that as all it knows at this stage is the file extension.
CSP should be set on all documents but, to save header bandwidth, does not need to be set on assets used by those documents (e.g. images, style sheets, javascript... etc). Other than wasted bandwidth there is no really harm in setting it on other documents.
Ideally you would set it based on the mime-type returned (which in the PHP example above would be HTML). So anytime a HTML document is returned then set it, else don't. However as this is not possible you're left with two choices:
Set it on everything by default but then explicitly unset it for known media types. This pretty much guarantees it will be set on the document but also risks it being set on a few other file types (e.g. if you don't explicitly unset it for that type) - which, as I say isn't really that bad.
Explicitly state your HTML document types (like your second example). The risk here is you miss a file type (e.g. .php) either now or when someone else starts using php on your site in future.
The first option is the safer option. Particularly for html5boiler plate where they have no idea what technology will be used on the site it's used on. A site might use .php, .cgi, .asp or any number of technologies to generate the HTML document. They could even proxy the request to a back end server so they would be no file extension.
Make sense?
I read that it's important to specify which file types you want to leverage browser caching with. However, what if you're confident you want a similar time-frame for ALL files to cache, can you just set a general command like this?
.htaccess code:
ExpiresActive On
ExpiresDefault "access 64 days"
That's what I did for my site and it seems to be functioning as I expected (caching everything). Is there anything wrong with doing this instead of specifying each individual file type?
It's very easy to do specific file types without doing a lot of work.
There are some things you might not want to cache like html pages etc. If you update your site, it might not be reflected immediately for some people unless they clear their cache. Most people don' t do that often. Don't be lazy. lol Just do the files that won't change often like images etc. One rule get's 5 extensions and more can be added.
<FilesMatch "\.(gif|jpg|png|js|css)$">
#expires in 1 month
Expires A2592000
</FilesMatch>
I have done lots of searching on here and applied a few of the methods mentioned without any luck.
My problem is a site I manage, the client uploads a new PDF under the same file name on a weekly basis. The problem is people are trying to download this, and lots are complaining that its loading the past weeks PDF. This is due to browser caching because when I tell them to clear their cache everything is OK.
I have two possible solutions:
1) Force the PDF file to download, vs opening in a new window. Now I have tried all sorts of these htaccess tweaks but none seem to work on IE9 or Safari.
2) Change the cache rate somehow, so that the cache rate for PDF files only lasts a minute, I have no idea how this could be done or if its even possible?
Does anyone have any solutions, rather then the obvious of just chaining the file name each time? The reason we dont do this is she wants to upload the PDFs on her own and not have to worry about editing the HTML file link.
Thanks in advance,
Matt
You can use the FilesMatch container and mod_headers to accomplish the prevention of cache in all browsers, clients, and proxies:
<FilesMatch ".pdf$">
FileETag None
<IfModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Thu, 1 Jan 1970 05:00:00 GMT"
</IfModule>
</FilesMatch>
Following the advice given by Yahoo / YSlow at http://developer.yahoo.com/performance/rules.html#expires I am trying to set a far future Expires header for my images.
In my .htacess I have:
<filesMatch "\.(jpg|jpeg|png|gif)$">
Header unset Pragma
FileETag None
Header unset ETag
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2014 20:00:00 GMT"
Header unset Last-Modified
</filesMatch>
Using Live HTTP Headers in Firefox I can see that there is no ETag and the Expires date shows as 2014. Also, looking at the cache I can confirm the Expires date and that there is no ETag or Server Last Modified date.
Again following the information given at YSlow I was expecting that if I now alter an image without altering its filename no changes would take effect until the Expires date is reached. YSlow points out that “if you use a far future Expires header you have to change the component's filename whenever the component changes”.
However, testing on localhost with XAMPP any change I make to an image is still immediately reflected on the web page if I refresh it.
Is this a local server thing or have I misunderstood how this is intended to work?
Thanks.