Optimizing Apache 2.2.3 Cache Control: Forcing Conditional Reloads Using Last-Modified Headers


2 views

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