跳转至

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 日发布。


Coverity Scan Buy Me a Coffee

此 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 时,映射到值 strongweak

注意:这些指令在 if 上下文中无效。建议使用 $varmap 来实现条件行为。

使用 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 仓库 中找到此模块的其他配置提示和文档。