为什么你的Nginx会无限308重定向?

📅 2026/7/9 8:10:05 👁️ 阅读次数 📝 编程学习
为什么你的Nginx会无限308重定向?

今天给一个私有化项目排查故障,问题表现是请求会返回无限308重定向,

最后定位是因为Nginx开启了强制HTTPS的重定向而未做判断。借这个机会,把Nginx的无限重定向的原理和处理方法给大家做下分享。

什么是 308 状态码?

308 Permanent Redirect 是 HTTP/1.1 协议中引入的状态码,与 301 类似但有一个关键区别:

  • 301/302:重定向返回可能会被浏览器将原本的 POST 请求改为 GET 请求
  • 307/308:严格保持请求方法和请求体不变
    • 307 = 临时重定向(对应302)
    • 308 = 永久重定向(对应301)

出现无限 308 重定向的常见场景

场景一:HTTPS 强制跳转配置错误

这是最常见的原因!

# 错误配置 - 无限重定向 server { listen 80; listen 443 ssl; server_name example.com; # 问题:没有判断是否已经是 HTTPS return 308 https://example.com$request_uri; }

问题原因:这个配置对 HTTP 和 HTTPS 请求都返回 308 重定向到 HTTPS,导致 HTTPS 请求也不断重定向自己。

正确配置

server { listen 80; server_name example.com; return 308 https://$host$request_uri; } server { listen 443 ssl; server_name example.com; # HTTPS 业务配置... }

场景二:CDN/负载均衡 + Nginx 配合问题

当请求经过 CDN 或负载均衡器后,HTTPS协议可能在CDN边缘节点已经终止,Nginx 收到的是 HTTP 请求,如果Nginx还是下面配置,就可能导致重定向:

# 错误配置 server { listen 80; server_name example.com; if ($scheme = "http") { return 308 https://$host$request_uri; } }

问题:用户使用HTTPS访问CDN,CDN回源到后端Nginx使用 HTTP,导致 Nginx 不断返回 308 让 CDN 跳转。

解决方法:信任X-Forwarded-Proto头:

server { listen 80; server_name example.com; # 客户端是HTTP才重定向,CDN是HTTP就不重定向了 if ($http_x_forwarded_proto != "https") { return 308 https://$host$request_uri; } }

场景三:多location块配合错误

# 错误配置 location /docs/ { rewrite ^/docs/(.*)$ /documentation/$1 permanent; } location /documentation/ { rewrite ^/documentation/(.*)$ /docs/$1 permanent; }

如果Nginx的配置文件由多人维护,这种情况出现频率还是很高的。


场景四:www 与非 www 互相重定向

# 错误配置 server { listen 443 ssl; server_name example.com www.example.com; # 非 www 转 www if ($host = "example.com") { return 308 https://www.example.com$request_uri; } # 又不小心写了反向规则! if ($host = "www.example.com") { return 308 https://example.com$request_uri; } }

检查方法:用 curl 测试看 Location 头:

# 输出中看 Location: 是否不断变化curl-Ihttps://example.com

场景五:trailing slash(末尾斜杠)配置冲突

# 错误配置 server { # 加斜杠 rewrite ^([^.]*[^/])$ $1/ permanent; # 又去斜杠 rewrite ^/(.*)/$ /$1 permanent; }

两个规则互相打架!这种情况相对比较少见。
上面是常见的导致无限重定向的配置错误,下面谈下如何诊断此类故障。


诊断无限重定向的方法

curl 跟踪重定向

# 只看头部curl-Ihttp://example.com# 跟踪最多5次重定向curl-IL--max-redirs5http://example.com

查看 Nginx 访问日志

# 看同一个 IP 短时间内的请求模式tail-f/var/log/nginx/access.log

临时改成 307 调试
之所以要这样改,是因为308重定向会被浏览器缓存,影响我们对故障的排查。

# 调试时先用临时重定向 return 307 https://...; # 或 302 rewrite ... redirect; # 不要用 permanent

常用重定向场景实战

场景:www 与非 www 互转

非 www 转 www

server { listen 443 ssl; server_name example.com; return 308 https://www.example.com$request_uri; }

www 转非 www

server { listen 443 ssl; server_name www.example.com; return 308 https://example.com$request_uri; }

场景:文件扩展名隐藏

# 访问 /about → 实际读取 /about.html location / { try_files $uri $uri.html $uri/ =404; }

场景:整站域名迁移

server { listen 80; listen 443 ssl; server_name old-domain.com www.old-domain.com; # 所有请求转到新域名,保持路径 return 301 https://new-domain.com$request_uri; }

场景:特定目录重定向

location ^~ /docs/v1/ { # 旧版本文档转到新版本 return 301 /docs/latest/; }

场景:移动端适配跳转

set $mobile_rewrite do_not_rewrite; if ($http_user_agent ~* "(android|iphone|ipad)") { set $mobile_rewrite rewrite; } if ($uri = "/mobile/") { set $mobile_rewrite do_not_rewrite; } if ($mobile_rewrite = rewrite) { return 302 /mobile/; }

希望这篇文章能帮助到你,欢迎转发、评论!