在 Web 服务器中实现 HTTP ETag

Implementing HTTP ETags in a web server

我目前正在研究在 Web 服务器中实现 ETag 的可能性,以仅支持条件 GET。 Web 服务器是用 C++ 编写的,仅在 Windows OS 上运行。在做了一些研究之后,我有几个问题...实现此功能的服务器通常会缓存特定文件的 ETag GUID 吗?我不太熟悉 Apache 代码库,但我能够找到 ap_condition_if_none_match 函数,但我并不完全清楚他们如何检查 if-none-match header。如果他们确实缓存了一些东西并且文件在服务器之外进行了任何更改(即用户更新了它),那么服务器如何知道其缓存中的文件不再有效?他们是否可能使用一些 API 到 "watch" 来更改目录?

编辑:我正在查看我在此处找到的一些信息:https://httpd.apache.org/docs/2.4/caching.html

在 Apache 中,ETag 由文件的索引节点、大小和最后修改时间构成:http://httpd.apache.org/docs/2.2/mod/core.html#FileETag

有不同的选项,您可以将它们设置为可配置的。我会给你一个可能的选项列表,从最不可靠到最可靠:

  1. [最快选项] 检查上次文件修改时间的频率高于 1 秒。例如,在 Windows 中,文件时间以 100 纳秒为间隔测量。还要像 Apache 一样检查文件大小和 inode。在 Windows 下,您可以通过 GetFileInformationByHandle 查询打开句柄的文件 ID,而不是 inode。参见 nFileIndexHigh、nFileIndexLow;这是 64 位文件 ID 的高低部分。如果文件时间、大小和 inode 发生变化,则重新计算哈希。
  2. [安全选项] 除了文件时间、大小和 inode 之外,还使用英特尔 (SSE4.2) 实现的非常快速的 CRC32 函数检查文件的内容——它比 SSE4 之前存在的任何 CRC32 实现都快得多。 2.如果文件时间或 CRC32 已更改,请重新计算哈希值。
  3. [快速且安全的选项,但会消耗句柄] 仅在您的服务器处于 运行 时才计算哈希值。当你的服务器第一次启动时,它应该没有计算哈希值。如果第一次请求文件,则计算哈希并存储它直到服务器退出。当服务器 运行 时,使用操作系统的文件更改通知监视文件更改(您具有哈希的文件)。比如在Widnows中,有FindFirstChangeNotification.

对于 ETag 本身的散列值,我会推荐一种加密散列函数,即使是对数字签名来说不再强大的散列函数。我不推荐没有明确设计为加密强度高的散列函数,因为它们不会产生像加密散列这样的小摘要,以达到可比的抗冲突水平。碰撞是指两个不同的文件产生相同的散列。 MD5 仍然非常适合文件内容更改监控 - 鉴于其高速和小摘要大小。它是最初为密码学设计的最快的 128 位散列函数。您还可以在汇编中找到一个快速的 MD5 实现,例如来自 OpenSSL 或来自 https://www.nayuki.io/page/fast-md5-hash-implementation-in-x86-assembly or https://github.com/maximmasiutin/MD5_Transform-x64 - 最后一个的性能是 4.94 CPU 在具有 Skylake 微体系结构的处理器上每字节周期。