dynamic-etag: NGINX 模块用于为动态内容添加 ETag
安装
您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:
- RedHat Enterprise Linux 7、8、9 和 10
- CentOS 7、8、9
- AlmaLinux 8、9
- Rocky Linux 8、9
- Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-dynamic-etag
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-dynamic-etag
通过在 /etc/nginx/nginx.conf 的顶部添加以下内容来启用模块:
load_module modules/ngx_http_dynamic_etag_module.so;
本文档描述了 nginx-module-dynamic-etag v0.2.3,于 2025 年 9 月 18 日发布。
此 NGINX 模块为您的动态内容提供自动 ETag 头。它允许客户端浏览器向动态页面发出条件 GET 请求,从而节省带宽并确保更好的性能!
首先注意事项!
此模块是一个真正的黑客:它从主体过滤器调用头过滤器等。
原作者放弃了它,不得不说:
它从来没有真正工作过。
我对其进行了大量重写,以处理现有的明显缺陷,但与缓冲区相关的关键部分,我自己年纪大了,可能永远也不会理解,保持不变。
为了可靠,模块必须读取整个响应并对其进行哈希。读取整个响应违背了 NGINX 轻量级设计。我不确定缓冲区部分是否等待整个响应。
话虽如此,我添加的测试展示了这一切都能正常工作!
请注意,HEAD 请求不会返回任何 ETag,因为我们没有数据可供处理,因为 NGINX 正确地丢弃了此请求方法的主体。
将其视为一个特性或一个错误 :-) 如果我们去掉这一点,那么所有 HEAD 请求最终都会有相同的 ETag(空值的哈希),这显然更糟。
因此,请确保您像这样检查头信息:
curl -IL -X GET https://www.example.com/
而不是这样:
curl -IL https://www.example.com/
另一个值得一提的是,在每次重新加载时都会更改的页面上应用动态 ETag 几乎没有意义。例如,我发现由于 <?= antispambot(get_option('admin_email')) ?>,我在 WordPress 主题的 header.php 中没有使用动态 ETag 的好处,因为在此函数中:
选择是随机的,每次调用函数时都会更改
要快速检查您的页面在重新加载时是否发生变化,可以使用:
diff <(curl http://www.example.com) <(curl http://www.example.com)
现在我们完成了“现在你知道”的内容,您可以继续尝试这些东西 :)
概述
http {
server {
location ~ \.php$ {
dynamic_etag on;
fastcgi_pass ...;
}
}
}
配置指令
dynamic_etag
- 语法:
dynamic_etag on|off|$var - 默认值:
off - 上下文:
http,server,location
启用或禁用自动应用 ETag。
dynamic_etag_types
- 语法:
dynamic_etag_types <mime_type> [..] - 默认值:
text/html - 上下文:
http,server,location
除了 text/html 外,自动为指定的 MIME 类型应用 ETag。特殊值 * 匹配任何 MIME 类型。具有 text/html MIME 类型的响应始终包含在内。
dynamic_etag_strength
- 语法:
dynamic_etag_strength strong|weak|$var - 默认值:
strong - 上下文:
http,server,location
控制生成的 ETag 是强还是弱。弱 ETag 对于动态内容很有用,即使字节不同,也应考虑语义相等(例如,时间戳、随机属性)。使用 $var 时,映射到值 strong 或 weak。
注意:这些指令在 if 上下文中无效。建议使用 $var 和 map 来实现条件行为。
使用 map 的示例:
map $arg_w $etag_strength {
default strong;
1 weak;
}
location /example {
dynamic_etag on;
dynamic_etag_types text/html;
dynamic_etag_strength $etag_strength;
proxy_pass http://backend;
}
提示
您可以使用 map 指令根据 URL 有条件地启用动态 ETag,例如:
map $request_uri $dyn_etag {
default "off";
/foo "on";
/bar "on";
}
server {
...
location / {
dynamic_etag $dyn_etag;
fastcgi_pass ...
}
}
原作者的 README
尝试处理代理内容上的 ETag / If-None-Match。
我计划用这个来前置一个使用大量 ESI 的 Varnish 服务器。
它确实有点工作,但……请注意,这是我第一次尝试开发 nginx 插件,而在读取主体后处理头并不是完全在操作手册中。
任何评论和/或改进和/或分叉都欢迎。
感谢 http://github.com/kkung/nginx-static-etags/ 的……灵感。
GitHub
您可以在 nginx-module-dynamic-etag 的 GitHub 仓库 中找到此模块的其他配置提示和文档。