0

Nginx return 301 保留参数后404错误?5个排查方向彻底解决问题

2026.05.30 | youres | 4次围观

问题现象

在 Nginx 配置中,为了让 HTTP 跳转 HTTPS 时保留查询参数(比如 UTM 追踪参数、分页参数 page 等),很多人会用 return 301 https://$host$request_uri; 这样的写法。配置看起来没问题,但跳转后浏览器却报 404,页面找不到。

这个问题在配置看起来"完全正确"的情况下尤其让人困惑。本文把最常见的 5 个原因逐一拆解,帮你快速定位并修复。

原因一:return 301 后面跟的 URL 路径和实际站点目录不匹配

这是最常见的原因。来看一个典型错误配置:

server {
    listen 80;
    server_name www.example.com;
    return 301 https://www.example.com$request_uri;
}

看起来没问题,但如果你的 HTTPS server 块里 root 路径配置错误,或者 location / 里的 root 指向了错误的目录,跳转后 Nginx 找不到对应的文件,就会返回 404。

排查方法:直接在浏览器访问 HTTPS 地址(不带参数),看是否 404。如果直接访问也 404,说明问题在 HTTPS server 块的 root 或 index 配置,和参数保留无关。

原因二:$request_uri 包含了错误的路径前缀

$request_uri 包含完整的原始请求 URI(含查询参数),但如果你在配置里手动拼接了路径,可能会重复或缺失。

错误示例:

# 错误:手动加了 / 前缀,和 $request_uri 里的 / 重复
return 301 https://$host/$request_uri;

$request_uri 本身就以 / 开头,上面这样写会变成 https://example.com//path?param=1,双斜杠在某些情况下会导致 Nginx 匹配不到 location,返回 404。

正确写法:

return 301 https://$host$request_uri;

不要手动加 /$request_uri 已经包含了。

原因三:HTTPS server 块里没有对应的 location 匹配

如果你的 Nginx 配置里 HTTPS server 块用了正则 location 或特定路径匹配,而跳转后的 URL 恰好匹配不到任何 location,就会返回 404。

典型场景:HTTPS 站点用了反向代理,但 proxy_pass 的路径和跳转后的 URI 对不上。

# HTTPS server 块
server {
    listen 443 ssl;
    server_name www.example.com;
    location /app/ {
        proxy_pass http://backend:8080/;
    }
}

如果跳转后的地址是 https://www.example.com/path?param=1,而 /path 没有对应的 location,就会 404。

排查方法:nginx -T 导出完整配置,检查 HTTPS server 块里是否有 location / 兜底,或者是否有正确的 proxy_pass 配置。

原因四:URL 编码参数导致路径解析异常

某些特殊字符(如 %#? 等)在查询参数里如果没有正确编码,Nginx 可能会把参数的一部分当作路径来处理,导致 404。

例如原始请求是:

http://example.com/search?q=hello%20world

如果 %20 被错误解码或编码,跳转后路径可能变成 /search?q=hello world(空格未编码),Nginx 无法正确解析,返回 404。

排查方法:用浏览器开发者工具查看 Network 面板,看跳转后的实际请求 URL 是什么,是否有乱码或异常字符。

原因五:CDN 或负载均衡在中间修改了请求路径

如果你的站点前面有 CDN(如 Cloudflare、阿里云 CDN)或负载均衡器,它们可能会在转发请求时修改 URI,导致后端 Nginx 收到的路径和预期不一致。

Cloudflare 的"始终使用 HTTPS"功能如果和 Nginx 自己的 return 301 同时开启,可能导致双重跳转,参数在中间丢失或路径被改写,最终 404。

排查方法:curl -vL http://your-site.com/path?param=1 查看完整的跳转链路,看每一跳的响应是什么,在哪一步出现了 404。

正确的 return 301 保留参数配置模板

综合上述排查,这里给出一个经过验证的安全配置模板:

# HTTP server 块:跳转 HTTPS 并保留所有参数
server {
    listen 80;
    server_name www.example.com example.com;
    return 301 https://www.example.com$request_uri;
}

# HTTPS server 块:确保 root 和 location 配置正确
server {
    listen 443 ssl http2;
    server_name www.example.com;
    root /var/www/html;
    index index.html index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # 如果是 PHP 站点
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

快速排查清单

  • 直接访问 HTTPS 地址(不带参数)是否 404?→ 检查 root/index 配置
  • 跳转后的 URL 是否有双斜杠(//)?→ 检查 $request_uri 前是否多了 /
  • HTTPS server 块是否有 location / 兜底?→ 用 nginx -T 检查
  • 跳转后 URL 是否有异常字符?→ 用 curl -vL 查看实际跳转链路
  • 前面是否有 CDN?→ 检查 CDN 的 HTTPS 跳转配置是否和 Nginx 冲突

相关文章

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论