<p>How do I generate an ETag HTTP header for a resource file?</p>

[{'answer_id': 4540, 'author': 'Mark Harrison', 'author_id': 116, 'author_profile': 'https://Stackoverflow.com/users/116', 'pm_score': 5, 'selected': True, 'text': '<p>An etag is an arbitrary string that the server sends to the client that the client will send back to the server the next time the file is requested.</p>\n<p>The etag should be computable on the server based on the file.  Sort of like a checksum, but you might not want to checksum every file sending it out.</p>\n<pre><code> server                client\n \n        &lt;------------- request file foo\n \n file foo etag: &quot;xyz&quot;  --------&gt;\n \n        &lt;------------- request file foo\n                       etag: &quot;xyz&quot; (what the server just sent)\n \n (the etag is the same, so the server can send a 304)\n</code></pre>\n<p>I built up a string in the format &quot;datestamp-file size-file inode number&quot;.  So, if a file is changed on the server after it has been served out to the client, the newly regenerated etag won\'t match if the client re-requests it.</p>\n<pre class="lang-c prettyprint-override"><code>char *mketag(char *s, struct stat *sb)\n{\n    sprintf(s, &quot;%d-%d-%d&quot;, sb-&gt;st_mtime, sb-&gt;st_size, sb-&gt;st_ino);\n    return s;\n}\n</code></pre>\n'}, {'answer_id': 4563, 'author': 'grom', 'author_id': 486, 'author_profile': 'https://Stackoverflow.com/users/486', 'pm_score': 3, 'selected': False, 'text': '<p>From <a href="http://developer.yahoo.com/performance/rules.html#etags" rel="noreferrer">http://developer.yahoo.com/performance/rules.html#etags</a>:</p>\n<blockquote>\n<p>By default, both Apache and IIS embed data in the ETag that dramatically reduces the odds of the validity test succeeding on web sites with multiple servers.</p>\n<p>...</p>\n<p>If you\'re not taking advantage of the flexible validation model that ETags provide, it\'s better to just remove the ETag altogether.</p>\n</blockquote>\n'}, {'answer_id': 6777, 'author': 'Justin Sheehy', 'author_id': 11944, 'author_profile': 'https://Stackoverflow.com/users/11944', 'pm_score': 4, 'selected': False, 'text': "<p>As long as it changes whenever the resource representation changes, how you produce it is completely up to you.</p>\n\n<p>You should try to produce it in a way that additionally:</p>\n\n<ol>\n<li>doesn't require you to re-compute it on each conditional GET, and</li>\n<li>doesn't change if the resource content hasn't changed</li>\n</ol>\n\n<p>Using hashes of content can cause you to fail at #1 if you don't store the computed hashes along with the files.</p>\n\n<p>Using inode numbers can cause you to fail at #2 if you rearrange your filesystem or you serve content from multiple servers.</p>\n\n<p>One mechanism that can work is to use something entirely content dependent such as a SHA-1 hash or a version string, computed and stored once whenever your resource content changes.</p>\n"}, {'answer_id': 106148, 'author': 'Rich Bradshaw', 'author_id': 16511, 'author_profile': 'https://Stackoverflow.com/users/16511', 'pm_score': 0, 'selected': False, 'text': '<p>I would recommend not using them and going for last-modified headers instead.</p>\n\n<p>Askapache has a useful article on this. (as they do pretty much everything it seems!)</p>\n\n<p><a href="http://www.askapache.com/htaccess/apache-speed-etags.html" rel="nofollow noreferrer">http://www.askapache.com/htaccess/apache-speed-etags.html</a></p>\n'}, {'answer_id': 7308209, 'author': 'lolesque', 'author_id': 787216, 'author_profile': 'https://Stackoverflow.com/users/787216', 'pm_score': 2, 'selected': False, 'text': '<p>How to generate the default apache etag in bash</p>\n\n<pre><code>for file in *; do printf "%x-%x-%x\\t$file\\n" `stat -c%i $file` `stat -c%s $file` $((`stat -c%Y $file`*1000000)) ; done\n</code></pre>\n\n<p>Even when i was looking for something exactly like the etag (the browser asks for a file only if it has changed on the server), it never worked and i ended using a GET trick (adding a timestamp as a get argument to the js files).</p>\n'}, {'answer_id': 14057468, 'author': 'peawormsworth', 'author_id': 1880288, 'author_profile': 'https://Stackoverflow.com/users/1880288', 'pm_score': 1, 'selected': False, 'text': '<p>Ive been using Adler-32 as an html link shortener. Im not sure whether this is a good idea, but so far, I havent noticed any duplicates. It may work as a etag generator. And it should be faster then trying to hash using an encryption scheme like sha, but I havent verified this. The code I use is:</p>\n\n<pre><code> shortlink = str(hex(zlib.adler32(link)+(2**32-1)/2))[2:-1]\n</code></pre>\n'}, {'answer_id': 63104602, 'author': 'Sergey Ponomarev', 'author_id': 1049542, 'author_profile': 'https://Stackoverflow.com/users/1049542', 'pm_score': 0, 'selected': False, 'text': '<p>The code example of Mark Harrison is similar to what used in Apache 2.2. But such algorithm causes problems for load balancing when you have two servers with the same file but the file\'s <code>inode</code> is different. That\'s why in Apache 2.4 developers simplified ETag schema and removed the <code>inode</code> part. Also to make ETag shorter usually they encoded in hex:</p>\n<pre class="lang-c prettyprint-override"><code>    \n&lt;inttypes.h&gt;\n    \n    \nchar *mketag(char *s, struct stat *sb)\n{\n    sprintf(s, &quot;\\&quot;%&quot; PRIx64 &quot;-%&quot; PRIx64 &quot;\\&quot;&quot;, sb-&gt;st_mtime, sb-&gt;st_size);\n    return s;\n}\n    \n</code></pre>\n<p>or for Java</p>\n<pre class="lang-java prettyprint-override"><code> etag = \'&quot;\' + Long.toHexString(lastModified) + \'-\' +\n                                Long.toHexString(contentLength) + \'&quot;\';\n</code></pre>\n<p>for C#</p>\n<pre class="lang-cs prettyprint-override"><code>// Generate ETag from file\'s size and last modification time as unix timestamp in seconds from 1970\npublic static string MakeEtag(long lastMod, long size)\n{\n    string etag = \'&quot;\' + lastMod.ToString(&quot;x&quot;) + \'-\' + size.ToString(&quot;x&quot;) + \'&quot;\';\n    return etag;\n}\n\npublic static void Main(string[] args)\n{\n    long lastMod = 1578315296;\n    long size = 1047;\n    string etag = MakeEtag(lastMod, size);\n    Console.WriteLine(&quot;ETag: &quot; + etag);\n    //=&gt; ETag: &quot;5e132e20-417&quot;\n}\n</code></pre>\n<p>The function returns ETag compatible with Nginx. See <a href="https://stackoverflow.com/questions/47512043/how-etags-are-generated-and-configured/62996104#62996104">comparison of ETags form different servers</a></p>\n'}]
['https://Stackoverflow.com/questions/4533', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/192/']