Custom etag generation Custom etag generation nginx nginx

Custom etag generation


In Apache, ETags are handled as a core feature. The ETag is computed as a hash of several values. You can use the FileETag directive in your httpd.conf or .htaccess file to define conditional behavior for which values to include in the hash, but as you pointed out, your options are limited to:

  • INode - your file's i-node number on the particular server it's served from
  • MTime - the timestamp (in millis) of the server your file is served from
  • Size - the size of your file in bytes
  • All - all of the above
  • None - none of the above

If you want truly custom ETag generation, you would definitely be best off writing an Apache module. However if you need a quick-and-dirty fix, you can generate your own tags by routing your requests to a PHP script and appending the Etag header in the script. The route might look like this in your httpd.conf or .htaccess file:

RewriteCond %{REQUEST_FILENAME} \.png$     # This example looks for .png requestsRewriteRule ^(.*)$ /gentag.php?path=$1 [B] # ...and routes them to a PHP script

The PHP script might look like this:

<?    $path = $_GET['path'];  // Grab the filepath from GET params    $cont = file_get_contents($path);  // Get file contents to hash    $hash = crc32($cont);   // Create your own ETag hash however you like    header("Etag: $hash");  // Send the custom Etag header    echo $cont;             // Dump the file contents to output?>


There are some comments in this PR that could address what your looking for. It isn't an algorithm of your choosing, but it is MD5, which is pretty solid.

You'll note that they present two options.

  1. Use the modified date of the file, but have a build process artificially mutate the modified date of the file based on a hash of the file. Then this modified date can be included in the ETag header calculation (don't use it as the Last-Modified header, as it may be in the future).
  2. Use the Content Digest feature of Apache to get an MD5 hash of the file as a header. You can then manipulate that as needed.