PHP重定向失效主因是Location头未被正确透传或改写:需确保PHP用绝对URL生成Location、Nginx透传Host/X-Forwarded-Proto头、配置proxy_redirect重写内网地址,并通过curl -v与access.log中$status/$upstream_status/$upstream_http_location三字段联合验证。

PHP 8.0 在 Nginx 环境下重定向失效,往往不是代码写错了,而是请求链路中某个环节“没传对”或“改错了”。重点不在 header("Location: ...") 这一行本身,而在于它生成的 Location 头能否被浏览器正确接收、解析并跳转。
看 PHP 实际输出的 Location 头是否完整
PHP 默认用相对路径生成重定向地址,比如 header("Location: /dashboard"),这在直连 PHP-FPM 时可能正常,但放在 Nginx 后面就容易出问题——浏览器拿到的是纯路径,没有协议和域名,跳转后地址栏只剩 /dashboard,当前域名丢失。
- 检查是否用了绝对 URL:应拼出完整地址,例如
header("Location: https://" . $_SERVER['HTTP_HOST'] . "/dashboard"); - 注意代理环境:若走 CDN 或负载均衡,
$_SERVER['HTTP_HOST']可能仍是原始值,需优先取$_SERVER['HTTP_X_FORWARDED_HOST']或$_SERVER['SERVER_NAME'](仅当 Nginx 显式透传且可信) - HTTPS 判断要严谨:不能只看
$_SERVER['HTTPS'] === 'on',还要兼容$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'和端口为 443 的情况
确认 Nginx 是否劫持或覆盖了 Location 头
Nginx 在反向代理场景下,可能静默修改、丢弃甚至重写响应头。尤其当后端返回 302 + 相对路径时,Nginx 若未配置 proxy_redirect,浏览器就会跳到错误位置。
- 确保有
proxy_set_header Host $host;:让后端生成跳转地址时参考的是用户最终访问的域名,而非内网地址 - 必须配
proxy_set_header X-Forwarded-Proto $scheme;:Spring Boot、Laravel、ThinkPHP 等框架依赖它判断协议,否则可能生成http://开头的跳转链接 - 加
proxy_redirect default;或显式规则,例如:proxy_redirect http://backend/ https://$host/;
用于把后端返回的内网地址(如http://192.168.1.100/login)重写成公网可访问地址
用 curl -v 直击真实响应头
绕过浏览器缓存和前端干扰,直接验证 Nginx 到底返回了什么:
立即学习“PHP免费学习笔记(深入)”;
- 执行
curl -v https://your-domain.com/login - 观察响应头中的
Location:字段内容 —— 是/dashboard?https://your-domain.com/dashboard?还是http://192.168.1.100/dashboard? - 对比直连后端(如
curl -v http://127.0.0.1:8080/login)的响应,确认差异是否来自 Nginx 层 - 若 Nginx 返回的是 301/302 但 Location 不对,问题就在 proxy_redirect 或 header 透传;若压根没返回 Location,说明 PHP 没执行到 header 行,可能是路由未进 PHP、脚本中断或 exit 被拦截
检查 Nginx 日志里有没有“悄悄失败”
开启带 upstream 字段的自定义日志格式,能快速定位是 Nginx 自己返回了 302,还是后端返回后被改错了:
- 在
log_format中加入:$status $upstream_status $upstream_http_location - 查看 access.log:若
$status = 302但$upstream_status = 200,说明 Nginx 自己生成了重定向(比如 rewrite 规则触发);若两者都是 302,再看$upstream_http_location的值是否合理 - 错误日志里搜索
rewrite or internal redirection cycle,这是循环重定向的典型提示



















