I've honestly spent a whole day on this and not closer to getting Nginx to play along properly especially with the way Nginx incorrectly formats the Last-Modified: Date header which is not within the RFC's for a Last-Modified header.
I found this solution however which, if you are using PHP, works just fine and can be tweaked as you need. Hope it helps. Just include this at the very top of your .php pages before the rest of your code.
<?php
//get the last-modified-date of this very file
$lastModified=filemtime(__FILE__);
//get a unique hash of this file (etag)
$etagFile = md5_file(__FILE__);
//get the HTTP_IF_MODIFIED_SINCE header if set
$ifModifiedSince=(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false);
//get the HTTP_IF_NONE_MATCH header if set (etag: unique file hash)
$etagHeader=(isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false);
//set last-modified header
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $lastModified)." GMT");
//set etag-header
//header("Etag: $etagFile");
header("ETag: \"$etagFile\"");
//make sure caching is turned on
header('Cache-Control: private, must-revalidate, proxy-revalidate, max-age=3600');
//check if page has changed. If not, send 304 and exit
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])==$lastModified || $etagHeader == $etagFile)
{
header("HTTP/1.1 304 Not Modified");
header("Vary: Accept-Encoding");
exit;
}
?>
Then test your site at redbot.org and www.hscripts.com
UPDATE:
- Added sending the vary header with the 304 not modified response (required)
- Modified Cache:Control header max-age can be tweaked to your own needs.
- To give credit where it is due, I found the solution here and tweaked it slightly - https://css-tricks.com/snippets/php/intelligent-php-cache-control/