RewriteRule & Header set Expires : how to - apache

I'm using rewrite rules to create a /fr /en on my website and does folder don't exist, therefore if I try to use
<Directory /fr>
ExpiresDefault "access plus 1 day"
</Directory>
Apache complain because the folder does not exist, can't find a way to do it in the http.conf
If I use
Header set Expires "access plus 1 day"
in the .htaccess, can see the header showing
Expires: access plus 1 day
instead of the date + 1 day, if i remove it I can see
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Also if I use
ExpiresDefault "access plus 1 day"
It does not work...
Can you please tell how to get this right?
Also I believe that Safari (and only safari) keep on reloading the page every minutes because of that, is that correct or just another issue?
Thx for your help!

Directory instructions are working on real filesystem paths. So a Directory setting should looks like :
<Directory /var/www/foo/bar/fr >
(...)
</Directory>
Instead, if you prefer working with url path you must use Location directives:
<Location /fr >
(...)
</Location>
This should at least fix your inexistents directories problems (if I understand your first sentence, which is quite strange)

Related

Add expires header for specific files

I am attempting to add an expires header for a specific file. It doesn't seem to be working and keeps setting it to one week. I'm not sure if it's a syntax error or the way I am trying to target the file.
Here is the code I am using in my HT Access.
<FilesMatch "^(vendor.min.js)$">
ExpiresByType text/javascript "access plus 4 weeks"
</FilesMatch>
In what context are your other Expires directives set? There are some counter-intuitive rules of how sections are merged, for example Location has higher precedence (evaluated later) than Directory/Files/FilesMatch.
I'd suggest changing the context of wherever your "1 week" rules are today.
https://httpd.apache.org/docs/2.2/sections.html

Apache: set max-age or expires in .htaccess for directory

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

Apache: ExpiresDefault doesn't work, whereas "Header" does. How comes?

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.

Overwrite cache-headers with mod_expires

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...

apache ExpiresDefault - just doesn't work

we all know that setting expire date for static files is very useful and the way i found to do so is through the ExpiresDefault property in a .htaccess file but it just doesn't work. I am using YSlow and page_speed to test the HTTP response, but it just keep on telling me that I need to set an expire date for my JS, CSS and images to speed up my application.
I tried to test ExpiresDefault "access plus 1 year" , locally ( apache server ) and on the web ( hostgator reseller account. if I have any options to make use of !?! ) but it just doesn't work. And it also doesn't return 500 error.
I feel like I am missing the main point or doing it wrong. How the whole thing should be done ?
First, identified mod_expires is compiled inside your apache.
Try
PATH_TO_YOUR/httpd -M | sort /* <-- look for expires_module*/
And your apache configuration should be like
ExpiresActive on
ExpiresDefault "access plus 1 year"
And always restart apache after configuration changed