When dealing with static resources on your website, proper cache control can significantly improve performance while ensuring users always get fresh content. The key mechanism here involves the Last-Modified
header and conditional requests.
For Apache 2.2.3, you'll want to modify either httpd.conf
or .htaccess
:
# Enable Last-Modified headers
FileETag MTime Size
# Set cache control for different file types
<FilesMatch "\.(html|htm|xml|txt|js|css)$">
Header set Last-Modified "%{%a, %d %b %Y %H:%M:%S GMT}t"
Header set Cache-Control "max-age=0, must-revalidate"
</FilesMatch>
For more precise control over when browsers should reload content:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 0 seconds"
<FilesMatch "\.(jpg|jpeg|png|gif|ico)$">
ExpiresDefault "access plus 1 month"
Header append Cache-Control "public"
</FilesMatch>
</IfModule>
For PHP or other dynamic pages, you should set headers programmatically:
<?php
$last_modified = filemtime(__FILE__);
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified)." GMT");
header("Cache-Control: no-cache, must-revalidate");
?>
Use curl to check headers:
curl -I http://yoursite.com/yourfile.css
Look for these response headers:
- Last-Modified: [timestamp]
- Cache-Control: no-cache, must-revalidate
- ETag: [value]
When browsers request resources from a web server, they can include headers like If-Modified-Since to check if a file has changed. Properly configured Apache can respond with 304 Not Modified status when content hasn't changed, saving bandwidth and improving performance.
Ensure these modules are loaded in httpd.conf:
LoadModule headers_module modules/mod_headers.so LoadModule expires_module modules/mod_expires.so
You can implement this either in:
- httpd.conf (server-wide configuration)
- .htaccess (directory-specific configuration)
For .htaccess (create if doesn't exist):
<IfModule mod_headers.c> Header set Last-Modified "" Header set ETag "" FileETag None </IfModule> <IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 month" ExpiresByType text/html "access plus 1 hour" </IfModule>
For better performance, configure directly in httpd.conf:
<Directory "/var/www/html"> Options FollowSymLinks AllowOverride All Require all granted <IfModule mod_headers.c> Header unset ETag Header set Cache-Control "max-age=0, must-revalidate" </IfModule> FileETag None </Directory>
After making changes, verify with:
sudo apachectl configtest sudo service apache2 restart
Then check headers using curl:
curl -I http://yoursite.com/example.html
For dynamic content (PHP, etc.), you may need additional headers:
<FilesMatch "\.(php|cgi|pl)$"> Header set Cache-Control "private, must-revalidate" Header set Last-Modified "" </FilesMatch>
- If Last-Modified isn't appearing, check mod_headers is loaded
- For ETag issues, disable with 'Header unset ETag' and 'FileETag None'
- Ensure your filesystem timestamps are accurate