Nginx 不生成或修改 HTTP 状态码,而是确保其准确返回:正确触发 304 需启用 etag 和 if_modified_since exact、避免 try_files 误将 404 转为 200、error_page 应保留原始 5xx 码而非覆盖为 200、重定向应按需选用 return 301/302 避免链式跳转。

Nginx 本身不生成或修改 HTTP 响应码(如 200、304、404、500)来“优化”它——响应码由请求处理流程自然决定,核心在于让正确的状态码准确返回、避免误覆盖、减少不必要的 4xx/5xx,并确保缓存与状态码语义一致。真正需要关注的是:资源是否存在、是否命中缓存、是否被重定向、后端是否出错,以及 Nginx 如何对这些情况做出恰当响应。
确保 304 Not Modified 正确触发
浏览器发起带 If-Modified-Since 或 If-None-Match 的条件请求时,Nginx 只有在启用相关模块且文件未变更时,才返回 304。这能省去响应体传输,但需满足前提:– 启用 etag on(默认开启)和 if_modified_since exact(推荐设为 exact,避免宽松比对导致误判)
– 静态文件需有可读的 mtime(修改时间),Nginx 才能比对;若文件系统挂载时禁用了 atime/mtime(如某些容器卷),304 将失效
– 不要手动 add_header ETag 或 Last-Modified:Nginx 自动设置,硬写可能冲突或格式错误,反而阻止 304
避免 404 被静默转成 200
常见错误是用 try_files + fallback 机制不当,导致本该 404 的资源返回 200 + index.html(典型于单页应用 history 模式):– 若仅服务静态资源(非 SPA),应禁用兜底逻辑:
location / {
root /var/www/static;
try_files $uri =404; # 明确终止,不 fallback
}
– 若必须支持 SPA,则区分路径:对 /api/ 等前缀返回 404,对 /assets/ 下资源严格 404,仅对根路径或 HTML 路径 fallback
– 检查日志中 access_log 的 $status 字段,确认真实返回码,而非只看浏览器 Network 面板(有时 DevTools 会隐藏重定向链)
统一处理 5xx 错误页面,但不掩盖真实状态
自定义错误页提升体验,但不能改变原始响应码:– 用 error_page 500 502 503 504 /50x.html; 是正确做法,Nginx 会返回 50x.html 内容,但状态码仍是 502(不是 200)
– 切勿使用 error_page 502 =200 /50x.html:这会把 502 强制改成 200,破坏监控告警和客户端重试逻辑
– 对 upstream 失败,可配合 proxy_next_upstream http_502 timeout,让 Nginx 自动重试另一节点,减少真实 502 返回次数
主动控制重定向状态码(301/302)
静态资源 URL 变更时,用明确重定向维持 SEO 和缓存一致性:– 用 return 301 比 rewrite … permanent 更轻量、更可控:
location = /old/style.css {
return 301 /new/v2/style.css;
}
– 区分永久(301)与临时(302):资源长期迁移用 301;A/B 测试或灰度发布用 302
– 避免链式重定向(A→B→C):每跳增加延迟,且部分客户端限制跳数;单步直达目标 URL


















