Nginx 中 if + rewrite 仅适用于轻量级单次条件重写,需加 break/redirect 避免循环;官方推荐用 map + try_files 替代以提升可维护性与健壮性。

Nginx 中的 if 指令本身不推荐用于复杂逻辑判断,尤其不能嵌套或用于 location 外部做重写决策;但配合 rewrite 实现简单条件路径重写是可行的——关键在于理解其限制和正确用法。
为什么 if + rewrite 要谨慎使用
if 在 Nginx 中属于“非标准上下文”,它在 location 块内才被允许执行,且每次匹配都会触发重写引擎重试(可能导致循环)。官方文档明确建议:优先用 map 替代 if 做变量映射,用 try_files 替代路径判断。
但若只是轻量级、单次判断(比如根据请求路径前缀或参数跳转),if + rewrite 仍可安全使用,前提是:
- rewrite 目标是绝对路径或带协议的 URL(避免内部重试)
- 结尾加
break或redirect/permanent阻止后续处理 - 不依赖多个
if组合(Nginx 不支持 else / elif)
常见条件路径重写示例
1. 根据 URL 路径前缀重写
把所有 /old/xxx 请求重写为 /new/xxx:
location /old/ {
if ($request_uri ~ ^/old/(.*)$) {
rewrite ^/old/(.*)$ /new/$1 break;
}
}2. 根据查询参数重定向
当有 ?v=beta 时,跳转到 beta 子域:
if ($args ~ "v=beta") {
rewrite ^(.*)$ https://beta.example.com$1? permanent;
}3. 根据 Host 和路径组合判断
仅对特定域名下的某路径启用重写:
server_name example.com;
if ($host = "example.com" && $uri ~ ^/admin/) {
rewrite ^/admin/(.*)$ /backend/$1 break;
}更健壮的替代方案:用 map + try_files
对于需要多条件、易维护的场景,推荐用 map 提前计算目标路径:
map $uri $new_path {
~^/old/(.*)$ /new/$1;
~^/legacy/(.*)$ /v1/$1;
default "";
}
<p>server {
location / {
if ($new_path) {
rewrite ^ $new_path break;
}</p><h1>后续正常处理</h1><pre class="brush:php;toolbar:false;"> try_files $uri @fallback;
}}
或者直接用 try_files 判断文件/目录是否存在后 fallback,避免 if:
location / {
try_files $uri $uri/ /index.php?$args;
# 若 /static/ 下无文件,则尝试 /assets/ 对应路径
location ^~ /static/ {
try_files $uri /assets$uri =404;
}
}必须注意的坑
rewrite 不会自动继承 location 的 root:内部重写后,Nginx 会重新匹配 location,所以 root 或 alias 需在目标 location 中明确定义。
if 内部无法使用 proxy_pass、fastcgi_pass 等指令:这些只能出现在 location 块顶层,if 里只允许 rewrite、set、return 等少数指令。
正则捕获变量在 if 外不可用:如 $1 只在当前 if 块内有效,不要试图在 if 外引用。
不复杂但容易忽略。


















