2026.05.30 | youres | 4次围观
在Nginx的实际使用中,内部重定向是一个绕不开的话题。有时候你配置了看似正确的rewrite规则,却发现访问内链时参数莫名其妙消失了。今天我们就来彻底解决这个问题。
先搞清楚:内部重定向和外部重定向的区别
很多人分不清这两种重定向的区别,所以配置的时候总是踩坑。
外部重定向(return/rewrite without flag or with [redirect]):浏览器地址栏URL变化,服务端返回302/301,浏览器发起新请求。这是我们最熟悉的方式。
内部重定向(rewrite with [last] or try_files):服务端在内部把请求转发给另一个location处理,浏览器地址栏不变,URL参数的行为也完全不同。
关键区别在于:内部重定向时,Nginx会重新走一遍location匹配流程,查询参数在某些情况下会被重新解析或丢失。
内部重定向参数丢失的4种场景
场景一:try_files配合内部重定向
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
当try_files最后一项是URI并带参数时,$args会自动附加。但如果PHP处理程序没有正确接收,就会出现参数丢失。
场景二:rewrite + last的循环匹配
location /old/ {
rewrite ^/old/(.*)$ /new/$1 last;
}
location /new/ {
# 这里$args仍然保留,但如果rewrite后又触发新的location匹配
# 并且新location有其他rewrite规则,参数可能被覆盖
}
场景三:内部重定向到带参数的location
server {
listen 80;
# HTTP到内部HTTPS的跳转(不改变浏览器URL)
rewrite ^(.+)$ https://$host$1 permanent;
# 如果这个server同时处理内部重定向
location /internal/ {
rewrite ^/internal/(.*)$ /proxy/$1 last;
}
location /proxy/ {
proxy_pass http://backend;
}
}
场景四:正则捕获组与参数的冲突
location ~ ^/article-(\d+)-(.*)$ {
rewrite ^/article-(\d+)-(.*)$ /detail?id=$1&title=$2 last;
}
location /detail {
# 此时原始的查询参数(?ref=xxx)会如何?
}
4种配置方案让参数完整保留
方案一:用$request_uri替代$uri+手动拼接
location / {
rewrite ^/old-path/(.*)$ /new-path/$1?$request_uri permanent;
}
# 或者在内部重定向时:
location /old/ {
set $orig_args $args;
rewrite ^/old/(.*)$ /new/$1 last;
}
location /new/ {
# 此时$args可能已变化,手动还原:
fastcgi_param QUERY_STRING $orig_args;
}
方案二:用map指令预提取参数
map $request_uri $base_args {
default ";
}
server 版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论