如何为资源文件生成ETag HTTP标头?
答案 0 :(得分:17)
只要资源表示发生变化,它就会发生变化,你如何产生它完全取决于你。
您应该尝试以另外的方式生成它:
如果不将计算出的哈希值与文件一起存储,则使用内容哈希值会导致#1失败。
如果重新安排文件系统或从多个服务器提供内容,则使用inode编号可能会导致#2失败。
一种可行的机制是使用完全依赖内容的内容,例如SHA-1哈希或版本字符串,每当资源内容发生变化时计算和存储一次。
答案 1 :(得分:16)
etag是服务器发送给客户端的任意字符串,客户端将在下次请求文件时将其发送回服务器。
etag应该基于文件在服务器上计算。有点像校验和,但您可能不希望校验和发送它的每个文件。
server client
<------------- request file foo
file foo etag: "xyz" -------->
<------------- request file foo
etag: "xyz" (what the server just sent)
(the etag is the same, so the server can send a 304)
我以“file inode number / datestamp / file size”格式构建了一个字符串。因此,如果在将服务器提供给客户端之后在服务器上更改了文件,则如果客户端重新请求它,则新重新生成的etag将不匹配。
char *mketag(char *s, struct stat *sb) { sprintf(s, "%d/%d/%d", sb->st_ino, sb->st_mtime, sb->st_size); return s; }
答案 2 :(得分:6)
来自http://developer.yahoo.com/performance/rules.html#etags:
默认情况下,Apache和IIS都在ETag中嵌入数据,这大大降低了在具有多个服务器的网站上成功进行有效性测试的几率。
...
如果您没有利用ETag提供的灵活验证模型,最好只删除ETag。
答案 3 :(得分:2)
如何在bash中生成默认的apache etag
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
即使我正在寻找与etag完全相同的东西(浏览器只在服务器上发生变化时才询问文件),它从未起作用,我结束时使用GET技巧(添加时间戳作为get参数) js文件)。
答案 4 :(得分:1)
我一直使用Adler-32作为html链接缩短程序。我不确定这是不是一个好主意,但到目前为止,我没有注意到任何重复。它可以作为etag生成器使用。它应该比使用像sha这样的加密方案尝试哈希更快,但我还没有验证这一点。我使用的代码是:
shortlink = str(hex(zlib.adler32(link)+(2**32-1)/2))[2:-1]
答案 5 :(得分:0)
我建议不要使用它们,而是选择最后修改的标题。
Askapache有一篇有用的文章。 (因为他们几乎做了所有的事情!)
答案 6 :(得分:0)
Mark Harrison的代码示例类似于Apache 2.2中使用的代码示例。但是,当两个服务器具有相同文件但文件的inode
不同时,这种算法会导致负载平衡问题。这就是为什么在Apache 2.4中,开发人员简化了ETag模式并删除了inode
部分。同样,为了使ETag更短,通常它们以十六进制编码:
<inttypes.h>
char *mketag(char *s, struct stat *sb)
{
sprintf(s, "\"%" PRIx64 "-%" PRIx64 "\"", sb->st_mtime, sb->st_size);
return s;
}
或Java
etag = '"' + Long.toHexString(lastModified) + '-' +
Long.toHexString(contentLength) + '"';
对于C#
// Generate ETag from file's size and last modification time as unix timestamp in seconds from 1970
public static string MakeEtag(long lastMod, long size)
{
string etag = '"' + lastMod.ToString("x") + '-' + size.ToString("x") + '"';
return etag;
}
public static void Main(string[] args)
{
long lastMod = 1578315296;
long size = 1047;
string etag = MakeEtag(lastMod, size);
Console.WriteLine("ETag: " + etag);
//=> ETag: "5e132e20-417"
}
该函数返回与Nginx兼容的ETag。参见comparison of ETags form different servers