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


11 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