如何制作与 Apache 匹配的 etag?
Posted
技术标签:
【中文标题】如何制作与 Apache 匹配的 etag?【英文标题】:How do you make an etag that matches Apache? 【发布时间】:2010-09-07 21:06:27 【问题描述】:我想制作一个与 Apache 生成的内容相匹配的 etag。 apache是如何创建它的etags的?
【问题讨论】:
【参考方案1】:Apache 使用标准的 inode-filesize-mtime 格式。唯一需要注意的是,mtime 必须是纪元时间并用零填充,因此它是 16 位数字。以下是如何在 php 中执行此操作:
$fs = stat($file);
header("Etag: ".sprintf('"%x-%x-%s"', $fs['ino'], $fs['size'],base_convert(str_pad($fs['mtime'],16,"0"),10,16)));
【讨论】:
为什么不header(sprintf('Etag: "%x-%x-%016x"', $fs['ino'], $fs['size'], $fs['mtime']));
?
我注意到我的 Apache 服务器的 ETag 的 MTime 部分实际上有一个更精确的 MTime,它也使用微秒。因此,如果您想完全按照 Apache 的方式生成 ETag,您将需要 mtime 的 microtime。据我所知,这在 PHP 中是不可能的。但是,您可以做的是检查 Apache 的 MTime 是否足够接近(304 Not Modified。【参考方案2】:
关于 Apache 的 Etag 需要记住的一点是,它们在集群中不能很好地发挥作用,因为它们包含的 inode 信息可能——而且可能会——在同一集群中的机器之间发生变化。
【讨论】:
将FileETag MTime Size
添加到您的 .htaccess 以使 Etag inode 独立。
在 Apache 2.4 版中,默认情况下不再包含 INode。【参考方案3】:
如果您是动态生成页面,那么这可能没有意义。如果您使用 PHP,您可以选择主脚本的 inode 和文件大小,但修改时间不会告诉您数据是否已更改。除非您有良好的缓存过程或只生成静态页面,否则 etag 没有帮助。如果您确实有一个良好的缓存过程,则 inode 和文件大小可能无关紧要。
编辑:对于那些不知道etags 是什么的人来说——它们应该是一个在内容发生变化时发生变化的值,用于缓存目的。浏览器从 Web 服务器获取 etag,将其与 etag 进行比较以获取其缓存副本,然后如果 etag 已更改,则获取整个页面。
【讨论】:
这种方法对于下载脚本(仅通过 PHP 流式传输文件)和其他响应实际上不是每个请求的动态的情况非常有用。【参考方案4】:上面的答案(来自 Chris)效果很好,但可以使用 sprintf 中的隐式转换来简化:
sprintf('"%x-%x-%x"', $s['ino'], $s['size'], str_pad($s['mtime'], 16, "0"));
建议的%016x
不起作用,因为填充是在转换为十六进制之后应用的,而不是之前。
【讨论】:
这 不 工作,我不知道为什么,可能是因为 %x 需要int
作为输入?
@FritsvanCampen:结果比这要复杂一些。 sprintf
将尝试将字符串转换为 int
,但由于这些数字太大,它们会溢出并导致问题。解决方案是改用float
:sprintf('"%x-%x-%x"', $s['ino'], $s['size'], (float) str_pad($s['mtime'], 16, '0'))
。以上是关于如何制作与 Apache 匹配的 etag?的主要内容,如果未能解决你的问题,请参考以下文章
Apache Pig - 如何获取多个包之间的匹配元素数量?