HTTP:生成ETag头

如何为资源文件生成一个ETag HTTP头?

0

6 答案

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)

我建立了一个格式为“文件索引号/日期戳/文件大小”的字符串。因此,如果服务器上的文件在服务器上发送给客户端后发生了更改,那么如果客户端重新请求它,则新重新生成的etag将不匹配。

char *mketag(char *s, struct stat *sb)
{
    sprintf(s, "%d/%d/%d", sb->st_ino, sb->st_mtime, sb->st_size);
    return s;
}
0
额外
就我而言,这是因为它是从CGI程序计算出来的路径。你说得对,如果是直接路径,那么这个时间可能就足够了。由于成本主要在stat()中,因此包含inode和大小并不需要额外的费用,这可以防止流氓管理员可能更新文件并将其重新接触到(当然不太可能)的情况原始的mtime。
额外 作者 Mark Harrison,
@MarkHarrison,你为什么需要etag的双引号?它是语法的强制部分吗?
额外 作者 Pacerier,
如果mtime是文件上次更改的时间,那么size和inode的用途是什么?
额外 作者 Steve,

我建议不要使用它们,而是使用最后修改的标题。

Askapache在这方面有一篇有用的文章。 (因为他们几乎看起来都是这样!)

http://www.askapache.com/htaccess/apache-speed-etags。 HTML

0
额外
嗯,这真是一种耻辱,希望他们很快回来,因为这个网站是建议的金矿!
额外 作者 Rich Bradshaw,
额外 作者 buhtz,
链接现在已备份。
额外 作者 Marius Gedminas,
@RichBradshaw只是一个问题,我们如何知道资源的最后修改时间戳?完成db更改历史记录后,完全是手动操作吗?或者有没有自动化的方法?
额外 作者 Supun Wijerathne,
askapache链接已损坏
额外 作者 bskinnersf,

http://developer.yahoo.com/performance/rules.html#etags

默认情况下,Apache和IIS都将数据嵌入到ETag中,这大大降低了在具有多个服务器的网站上成功进行有效性测试的几率。      

...

     

如果您没有充分利用ETags提供的灵活验证模型,最好是完全删除ETag。

0
额外

只要资源表示发生变化,只要它发生变化,您如何生成它完全取决于您。

您应该尝试以另外的方式制作它:

  1. 不要求您在每个条件GET上重新计算它,
  2. 在资源内容未更改时不会更改

如果不将计算出的散列与文件一起存储,则使用散列的内容可能会导致您在#1失败。

如果重新排列文件系统或者从多个服务器提供内容,使用inode编号可能会导致您在#2失败。

可以工作的一种机制是使用完全依赖于内容的内容,例如SHA-1哈希或版本字符串,只要您的资源内容发生变化就计算并存储一次。

0
额外

如何在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技巧(将时间戳添加为js文件的get参数)。

0
额外

我一直使用Adler-32作为html链接缩写。林不知道这是否是一个好主意,但到目前为止,我没有注意到任何重复。它可能作为一个etag生成器。而且它应该更快,然后尝试使用像sha这样的加密方案进行散列,但是我没有验证过这一点。我使用的代码是:

 shortlink = str(hex(zlib.adler32(link)+(2**32-1)/2))[2:-1]
0
额外