Language agnostic HTTP:生成ETag头

Language agnostic HTTP:生成ETag头,language-agnostic,http,webserver,header,etag,Language Agnostic,Http,Webserver,Header,Etag,如何为资源文件生成ETag HTTP头?ETag是服务器发送给客户端的任意字符串,客户端将在下次请求文件时将其发送回服务器 etag应该可以在服务器上基于文件进行计算。有点像校验和,但您可能不希望对发送它的每个文件进行校验和 server client <------------- request file foo file foo etag: "xyz" --------> <

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

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)
发件人:

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

如果您没有利用ETag提供的灵活的验证模型,那么最好完全删除ETag


只要它在资源表示发生变化时发生变化,那么如何生成它完全取决于您自己

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

  • 不需要在每个条件GET上重新计算它,并且
  • 如果资源内容未更改,则不会更改
  • 如果不将计算出的哈希值与文件一起存储,则使用内容哈希可能会导致在#1处失败

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


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

    我建议不要使用它们,而是使用上次修改的标题

    Askapache对此有一篇有用的文章。(因为他们几乎做了所有看起来的事情!)


    如何在bash中生成默认的apacheetag

    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文件中)。

    我一直在使用Adler-32作为html链接缩短器。我不确定这是否是个好主意,但到目前为止,我还没有发现任何重复的。它可以作为etag发生器工作。它应该比使用像sha这样的加密方案进行散列更快,但我还没有对此进行验证。我使用的代码是:

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

    Mark Harrison的代码示例与Apache2.2中使用的类似。但是,当两台服务器具有相同的文件,但文件的
    inode
    不同时,这种算法会导致负载平衡问题。这就是为什么在Apache2.4中,开发人员简化了ETag模式并删除了inode部分。此外,为了使ETag更短,通常使用十六进制编码:

    
    char*mketag(char*s,struct stat*sb)
    {
    sprintf(s,“\”%“PRIx64”-“%PRIx64”\”,sb->stu-mtime,sb->stu-size);
    返回s;
    }
    
    还是Java

    etag=''''''+Long.tohextstring(lastModified)+'-'+
    Long.tohextString(contentLength)+''”;
    
    对于C#

    //从1970年开始,根据文件大小和上次修改时间生成ETag作为unix时间戳(以秒为单位)
    公共静态字符串MakeEtag(长lastMod,长尺寸)
    {
    字符串etag=''''''+lastMod.ToString(“x”)+'-'+size.ToString(“x”)+'';
    返回etag;
    }
    公共静态void Main(字符串[]args)
    {
    长lastMod=1578315296;
    长尺寸=1047;
    字符串etag=MakeEtag(lastMod,size);
    控制台写入线(“ETag:+ETag”);
    //=>ETag:“5e132e20-417”
    }
    

    该函数返回与Nginx兼容的ETag。看

    Hmm,那太可惜了,希望他们能尽快回来,因为网站是一座咨询的金矿@RichBradshaw只是一个问题,我们如何知道资源最后修改的时间戳?在经历数据库更改历史后,是否完全是手动操作?或者有什么自动化的方法吗?如果mtime是文件最后一次更改的时间,那么大小和inode的用途是什么?在我的例子中,这是因为它是CGI程序的计算路径。你是对的,在直接路径的情况下,mtime可能就足够了。由于成本主要是在stat()中,因此不需要额外的费用来包含inode和size,这可能会防止(当然不太可能)流氓管理员更新文件并将其恢复到原始的mtime。@MarkHarrison,为什么在etag周围需要双引号?它是语法的强制部分吗?