nginx全站启用http/2后,301重定向本身不受协议影响,关键在于严格分离80端口跳转(仅return 301 https://$host$request_uri)与443端口https服务(listen 443 ssl http2;配证书及安全头),避免混用、if判断或头覆盖导致异常。

全站启用 HTTP/2 后,Nginx 的 301 重定向本身不受协议版本影响,但链路稳定性取决于配置结构是否合理——关键不是“HTTP/2 是否支持 301”,而是跳转逻辑是否与协议分层、端口分离、头信息透传协同一致。
HTTP/2 只在 HTTPS(443)端口生效,80 端口跳转必须独立
HTTP/2 是 TLS 层协议,只能运行在启用了 SSL 的 443 端口。因此:
- 所有 301 跳转逻辑(尤其是 HTTP→HTTPS)必须放在 单独的 listen 80 server 块 中,不能混进 443 的 HTTPS 配置里
- 这个 80 块只需 return 301 https://$host$request_uri;,不加 ssl 相关指令,否则 nginx -t 会报错
- 443 块则专注提供服务:listen 443 ssl http2; + 正确证书路径 + 安全头(如 HSTS)
避免因 HTTP/2 优化引发的跳转异常
HTTP/2 启用后,部分优化项可能间接干扰重定向行为:
- 禁用
if ($scheme = http) { rewrite ... }:HTTP/2 下 if 指令更易触发不可预测匹配,坚持用return 301直接响应 - 不要在 443 server 块中写跳转逻辑:例如 “如果没登录就跳首页”,这类业务跳转若返回 301,又未正确处理 referer 或 cookie,可能被 HTTP/2 的多路复用放大响应延迟或缓存误判
- 确保
add_header不覆盖关键头:比如误加add_header Location ...会破坏 301 响应头,导致浏览器无法识别跳转
多级代理或 CDN 场景下保障跳转链路完整
当 HTTP/2 终结在 CDN 或前端 Nginx,后端仍为 HTTP 时,需防止协议感知断裂:
- 一级入口(CDN 或 LB)用
return 301 https://$host$request_uri;强制跳转 - 中间层 Nginx 必须透传
X-Forwarded-Proto $scheme;,否则后端应用(如 PHP、Node.js)可能误判为 HTTP 并自行跳转,造成 http↔https 循环 - 后端服务需信任该头(如 Django 设为
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'))
验证要点:不止看跳转,还要看协议协商结果
确认稳定性的实际检查项:
- 用
curl -I http://example.com:应返回HTTP/1.1 301(80 端口走 HTTP/1.1 是正常行为) - 用
curl -I https://example.com:响应头中应含HTTP/2 200,且无 301(说明跳转已完成,后续请求直连 HTTPS) - 浏览器开发者工具 → Network 标签页:检查跳转请求的 Protocol 列,首次跳转是 h1,目标页应为 h2
- 执行
openssl s_client -alpn h2 -connect example.com:443验证 ALPN 协商成功











