nginx配置etag实现协商缓存的核心是etag与last-modified协同工作:默认只发last-modified,需显式配置etag on启用弱etag,且etag依赖last-modified存在;搭配cache-control "public, max-age=0, must-revalidate"强制验证。

Linux 下 Nginx 配置 ETag 实现协商缓存,核心不是“加一个头”,而是让 ETag 与 Last-Modified 协同工作、不冲突、且符合客户端实际验证逻辑。Nginx 默认只发 Last-Modified,ETag 必须手动启用,且仅对已含 Last-Modified 的响应生效。
确认后端是否返回 Last-Modified
ETag 在 Nginx 中不会凭空生成——它依赖于响应中已存在的 Last-Modified 头(Nginx 用文件 mtime 自动设置该头,但仅限静态文件托管场景)。若你代理的是 API(如 /api/),需先检查真实响应:
- 执行 curl -I https://your-domain.com/static/app.js 或 curl -I https://your-domain.com/api/data
- 确认响应中包含 Last-Modified(推荐)或已有 ETag
- 若无,需在后端添加:Express 用
res.set('Last-Modified', stats.mtime.toUTCString());FastAPI 用Response(headers={"Last-Modified": ...})
在 Nginx 中启用 ETag 生成
只需一行配置,放在 server 或 location 块内即可,无需额外模块:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
- 添加 etag on; —— 这是唯一必需指令,默认为 off
- 不要同时用
add_header ETag和etag on,否则可能冲突 - 静态资源(.js/.css/.png)由 Nginx 直接服务时,
etag on会基于文件大小 + mtime 生成弱 ETag(格式为W/"size-mtime")
搭配 Cache-Control 明确协商意图
光有 ETag 不够,客户端必须知道“该去问服务器”。靠 Cache-Control 控制行为:
- 推荐配置:add_header Cache-Control "public, max-age=0, must-revalidate";
- 避免仅设
no-cache:语义正确但易被误读,且部分客户端可能跳过协商流程 - 不要用
expires覆盖协商逻辑;也不建议设immutable,它会禁用协商缓存
验证是否生效
生效后,客户端第二次请求会自动携带验证头:
- 用 curl -H "If-None-Match: \"xxx\"" https://... 测试,应返回 304 Not Modified
- Chrome DevTools → Network → 查看请求的 Request Headers 是否含
If-None-Match,Response Headers 是否为 304 - 注意:若后端返回了
Cache-Control: no-store或未配must-revalidate,协商可能被跳过










