Nginx rewrite不支持多条件组合,需通过嵌套if、map预判、正则隐式判断或try_files+内部重定向实现;推荐map指令,慎用嵌套if,复杂逻辑应交由应用层处理。

Nginx 的 rewrite 指令本身不支持多条件组合(比如 if (a && b) { rewrite ... }),它只能配合 if 指令做单条件判断,而 if 在 location 块中又受限较多。真正实现“多条件组合”的核心方式是:用多个 if 嵌套或借助 map 指令预判,再在 rewrite 中引用结果。
下面说几种实用、安全、可读性强的写法:
用嵌套 if 实现 AND 逻辑
虽然 Nginx 官方不推荐深层 `if`,但在简单场景下,嵌套 `if` 是最直接模拟 `&&` 的方式:
location /old/ {
if ($arg_id ~ ^\d+$) {
if ($arg_type = "article") {
rewrite ^/old/(.*)$ /new/article/$1? permanent;
}
}
}
说明:只有当 查询参数 id 是纯数字 且 type 等于 article 时才触发重写。注意:嵌套 if 仅限于 server 或 location 块内,且不能包含 break、return 等复杂指令。
用 map 预定义组合条件(推荐)
`map` 指令在全局(http 块)中定义变量,性能好、逻辑清晰,适合多条件判断:
http {
map "$arg_id:$arg_type" $should_rewrite {
default 0;
"~^\d+:article" 1;
"~^\d+:user" 1;
}
<pre class="brush:php;toolbar:false;">server {
location /old/ {
if ($should_rewrite = 1) {
rewrite ^/old/(.*)$ /new/$arg_type/$1? permanent;
}
}
}}
说明:把多个参数拼成字符串(如 "123:article"),用正则匹配组合值。这种方式避免了嵌套 `if`,也规避了 `if + rewrite` 在某些上下文中的不可靠行为。
用正则在 rewrite 中隐式判断(适用于路径+参数混合)
如果条件能统一到 URI 或 `$args` 字符串里,可直接用 `rewrite` 的正则捕获 + `?` 控制参数:
rewrite ^/old/(?<id>\d+)/?(?:\?.*id=(?<id2>\d+).*type=(?<type>\w+))?$ /new/$type/$id? permanent;</type></id2></id>
实际更稳妥的做法是结合 `if` 和 `rewrite`:
if ($args ~* "id=(\d+)&type=article") {
set $match_id $1;
rewrite ^/old/.*$ /new/article/$match_id? permanent;
}
注意:`$args` 是原始查询字符串,不含 ?,且大小写敏感;用 `~*` 表示忽略大小写匹配。
避开 if:用 try_files + 内部重定向(适合复杂路由)
对需要多条件跳转的场景,可把逻辑下沉到后端或用命名 location 分流:
rewrite ^/internal-rewrite$ /api/v1/content?last_uri=$arg_type&id=$arg_id break;
说明:用 `internal` 限制内部访问,配合 `last` 跳转,让后续 location 继续处理,比堆砌 `if` 更可控。
不复杂但容易忽略:Nginx 的 if 是“伪指令”,它的执行时机和作用域有陷阱,涉及 $request_uri、$args、重写后的变量等要格外小心。优先用 map,慎用嵌套 if,复杂逻辑尽量交给应用层。











