Apache2 mod_expires not working - apache

I have recently deployed a website on a VPS that supports Apache2, and was working on performance improvement suggestions by YSlow.
Among those improvements were using mod_deflate and mod_expires, and since I have root access, I can directly edit the Apache config files.
mod_deflate is now working, but I am having issues with mod_expires so here is what I have done:
enable expires module and restart the server
a2enmod expires
service apache2 restart
create a new file "expires.conf" under mods_enabled that contains the following:
<IfModule mod_expires.c>
# Enable expirations
ExpiresActive On
# Default directive
ExpiresDefault "access plus 1 month"
# My favicon
ExpiresByType image/x-icon "access plus 1 year"
# Images
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
# CSS
ExpiresByType text/css "access plus 1 month"
# Javascript
ExpiresByType application/javascript "access plus 1 year"
</IfModule>
However, when checking on various browsers Dev Tools under Network, the files show a Cache Control of None.
I thought of using my mod_expires script above in a .htaccess located in the root directory of my website: /var/www/sitename/public_html, since settings in the .htaccess override any prior settings made in the apache config files.
For that, i enabled the use of htaccess in apache2.conf.
I tested that my htaccess file was indeed working by willingly introducing an error in it (commented out the IfModule open tag). Refreshing the browser gave me a 500 server error. So the htaccess file was being processed.
Unfortunately, the browser dev tools still showed no cache control, and I am running out of ideas.
Am I missing something?
Thanks!

Most likely, your expires.conf is getting parsed before the expires module is loaded, as you have included the configuration file in the mods-enabled folder.
Place your config file in conf.d and restart Apache.

I finally fixed the issue:
firstly i noticed a difference between all the other config files and the one i had created under mods-enabled: the others were symlinks to their respective files under mods-available. This shouldn't be an issue but definitely better stick to the convention.
It seems I may not have restarted the apache2 service after creating the file

In my case, I had to:
Move the expires.conf to /etc/apache2/conf-available/ . I think this would be necessary to load the configs after the module.
mv /etc/apache2/mods-available/expires.conf /etc/apache2/conf-available/
Also I had forgotten to enable the config before restarting apache.
a2enconf expires
service apache2 reload

Related

How can I make browsers cache html files?

I want browsers to cache html files. I set up Apache2.4 and confirm css, js, png are cached, but html files are never cached.
Chrome 90 and Edge 90
Apache 2.4
/etc/httpd/conf/httpd.conf
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 30 days"
</IfModule>
Hi try to add ExpiresByType text/html "access plus 7200 seconds". Hope it works !

Managing/Updating headers in Apache Server

We are using Apache as our Web server for our CRM application (Siebel) . We continuosly deploy new JS and CSS files on the CRM application in 15 days Currently we have the following setting.
FileETag None
ExpiresActive On
<IfModule mod_expires.c>
ExpiresByType text/css "access plus 5 days"
ExpiresByType text/javascript "access plus 5 days"
ExpiresByType image/gif "access plus 5 days"
ExpiresByType image/jpg "access plus 5 days"
ExpiresByType image/png "access plus 5 days"
ExpiresByType application/x-shockwave-flash "access plus 5 days"
ExpiresByType application/x-javascript "access plus 5 days"
AddType image/x-icon .ico
ExpiresByType image/x-icon "access plus 5 days"
</IfModule>
In this case if we have a Hotfix release we have to ask the end users to clear their cache so that the new files can be reflected from their side else they have to wait till the objects expire and are auto refreshed.
If we set it to a lower value than the requests to the web server increase and the load increases on web server.
I would like to know is there any mechanism.
1) To auto update the new files on end user machine automatically when a new file is placed .
2) To set expiration of folder level rather than a file level.
Thanks
In response to point 1)
I'd suggest using versioning at the URL level.
I.E mysite.com/lib/js.js?v=1, mysite.com/lib/style.css?v=1 (etc.. etc..)
When you roll out a new version, update this to v=x (and so on).
There is no way of forcing a client to flush it's cache, mainly due to all the browsers being implemented different (they'd all have to implement this), and it would no doubt be some risk of security.
As for point 2) maybe this question might help:
ServerOverflow - Apache: ExpiresByType per directory?

PHP site not showing cache-control. Not caching anything

INTRO
I have a task to fix existing site's problem that nothing is being cached (except for browser session). When closing session and opening browser again, page loads a lot of images, JS and CSS again. As I have ~60 items every time, there is a big load problem.
PROBLEM
Looking at Chrome console, Audit shows The following resources are missing a cache expiration...
And in Network item in "Response Headers" doesn't even show "cache-control" line.
TRIED SOLUTIONS
I have set info in .htaccess file and made sure mod_expires is active:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>
I added Cache-control meta-tag in html head that is also showing in page's code source so it is compiled.
<meta http-equiv="Cache-control" content="public" content="max-age=604800">
And I'd like to add that it most likely isn't a server issue as production page's host has set it to a usual default. (And I don't have access to that server anyways)
I'd be super delighted, if someone could give me some pointers of what I am missing or haven't checked or simply don't understand.
Added main.css headers
Thanks!
You can set the headers through php since this is a php site.
<?php
header("Cache-Control: max-age=2592000"); //30days (60sec * 60min * 24hours * 30days)
?>
Also you can use the FilesMatch like this in your .htaccess
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
Well, although stupid (as I expected), but I didn't read about it anywhere and just forget about the need of it.
Solution
It turned out all those things changed (as I said everything was activated on server, access files etc). And the problem was that I didn't clear the cache after changing caching info. Now after three days I started working on some CSS, needed to reset the cache and boom - all the new headers are active for all the items.

Setting expire headers and gzipping data via .htaccess

I'm trying to set it up so that the browser will cache the webfonts for a long period and also attempting to gzip them for a faster download.
From what I can understand you can do this via your httpd.conf file in Apache or via .htaccess.
I'm not sure how to tell if gzip is enabled though, I read something about searching your httpd.conf file for DEFLATE; I did that, but found nothing - so not sure if it's enabled or not!?
Anyway, I have put this code below into the .htaccess file, partially because I didn't know where to put it in the httpd.conf file and partially because it's easier to make changes in .htaccess file without bothering my host continually.
Here is the code..
# Add correct content-type for fonts
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType font/x-woff .woff
AddType image/svg+xml .svg
# Compress compressible fonts
AddOutputFilterByType DEFLATE font/ttf font/otf image/svg+xml
# Add a far future Expires header for fonts
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
ExpiresByType font/x-woff "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
Now, I'm wondering if this is correct or not as I also seen this similar, but different code for the expiry..
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
Does it matter where you place it in the .htaccess file or can it go anywhere?
ExpiresByType can go in your httpd.conf, virtualhost config or htaccess, as shown in the apache documentation overview box at the top of each directive entry:
http://httpd.apache.org/docs/2.2/mod/mod_expires.html#expiresbytype
The Context listing is how you can tell which configuration files you can put your various Apache directive types into.
Assuming you are using PHP, your phpinfo details should tell you if gzip is enabled.
Edit
In response to your question about correct way MIME type for your fonts, in terms of their file association with the Apache Server, my mime.types file (found in apache conf folder where your httpd.conf lives) tells me that
application/x-font-(extension)
would be the association to use with ExpiresByType. I would suggest getting the fonts working first, and then checking the headers for the font url to see if its giving proper expiration date.
As for the browsers receiving the web fonts, this article seems to indicate that MIME types aren't considered and thus don't matter. But yet this one seems to contradict that. As I understand it, there is no official font/ MIME type so any browser implementation is outside the MIME specifications.
Related questions:
Proper MIME type for fonts
Correct Apache AddType directives for font MIME types
I've not seen anything specifying placement requirements in .htaccess so you should be safe putting these rules wherever you see fit, although if you do AddTypes you need to do so above any further directives that reference that declared Type. It's probably best to put these near the top above your rewrite rules.

Last modification date of web page unknown

I would like to check the age of the document in the webpage, but it does not show! Here is the result of a telnet to the server:
telnet av.hostoi.com 80
Connected to av.hostoi.com. HEAD / HTTP/1.0
HTTP/1.1 200 OK Date: Tue, 23 Oct 2012 16:55:40 GMT
Server: Apache
X-Powered-By: PHP/5.2.17
Connection: close
Content-Type: text/html
Connection closed by foreign host.
On another server the following 2 lines are also included which are not present above:
Last-Modified: Fri, 17 Jun 2011 11:17:45 GMT
ETag: "2ce392-b1-4a5e688eae840"
So I searched the Internet and as far as I could figure out, there should be a configuration in Apache to set headers on and etag on in htaccess. But I couldn't find any place that shows me that.
Here are the loaded modules in Apache if it would help:
core mod_authn_file mod_authn_default mod_authz_host mod_authz_groupfile mod_authz_user mod_authz_default mod_auth_basic mod_include mod_filter mod_log_config mod_env mod_expires mod_headers mod_setenvif mod_version prefork http_core mod_mime mod_status mod_autoindex mod_asis mod_info mod_vhost_alias mod_negotiation mod_dir mod_actions mod_alias mod_rewrite mod_so mod_php5 mod_ruid2
As far as I read mod_header must be enabled which seems to be the case.
Any help on this?
edit:
tried the proposed solution:
put a .htaccess file in / folder even though there is a file named do not upload here.
contents of .htaccess:
<code>
# Do not remove this line, otherwise mod_rewrite rules will stop working
RewriteBase /
Options -Indexes
SSILastModified on
<IfModule mod_expires.c>
FileETag MTime Size
ExpiresActive on
ExpiresDefault "access plus 10 days"
ExpiresByType application/javascript "access plus 1 week"
ExpiresByType application/x-javascript "access plus 1 week"
ExpiresByType application/x-shockwave-flash "access plus 1 week"
ExpiresByType text/css "access plus 1 week"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/x-icon "access plus 6 month"
ExpiresByType image/ico "access plus 6 month"
</IfModule>
</code>
i put this file in public_html folder and in the sub folder nod_update3 where the file update.ver exists.
then i execute the script that checks the age of the document like so:
./check_http -H av.hostoi.com -u /nod_update3/update.ver -M 2d
HTTP CRITICAL: HTTP/1.1 200 OK - Document modification date unknown - 26316 bytes in 0,159 second response time |time=0,158965s;;;0,000000 size=26316B;;;0
as you can see no modification date is shown even though on the ftp client it shows it was last modified 25.10.2012
i tried the check on another file in the same folder like so:
./check_http -H av.hostoi.com -u /nod_update3/em000_32_l0.nup -M 2d
HTTP CRITICAL: HTTP/1.1 200 OK - Last modified 13,5 days ago - 56472 bytes in 1,059 second response time |time=1,059014s;;;0,000000 size=56472B;;;0
srvmon plugins #
as you can see the date modification is known. so why the problem with ver file?
the file can be checked in this url:
http://av.hostoi.com/nod_update3//update.ver
The problem is that you have caching of static content enabled on first server, and on second one that is not the case.
Please take a look in apache main configuration file,virtual host or .htacess on second server
if you have something similar to:
<IfModule mod_expires.c>
FileETag MTime Size
ExpiresActive on
<filesMatch "\.ver$">
ExpiresDefault "modification plus 2 week"
</filesMatch>
</IfModule>
Also you need to enable apache module mod_expires.
Hope this helps!
By tracking back to the source code of Apache, we can see the root cause of this misconfiguration is that the semantics enabled by "Xbithack Full" implicitly overwrite the semantics enabled by "SSILastModified On".
if (conf->lastmodified > 0) {
... {
ap_update_mtime(r, r->finfo.mtime);
ap_set_last_modified(r);}}
else if (((conf->xbithack == XBITHACK_FULL ||
(conf->xbithack == XBITHACK_UNSET &&
DEFAULT_XBITHACK == XBITHACK_FULL))
...)) {
ap_update_mtime(r, r->finfo.mtime);
ap_set_last_modified(r);
}
One possible solution here is to replace "SSILastModified on" with "Xbithack Full".