nginx 的 if 指令可在 location 块中基于变量(如 $arg_env、$http_user_agent)做简单条件判断实现基础分流,但不支持嵌套和逻辑运算,proxy_pass 等指令不可直接写入 if 块,复杂场景应优先使用 map 指令或交由后端处理。

Nginx 的 if 指令可以在 location 块中做简单条件判断,用于基础的业务分流(比如按请求参数、Header 或域名跳转),但要注意它有局限性和潜在风险,不能替代完整的逻辑处理(如复杂路由应交给后端或用 OpenResty)。
哪些条件能用 if 判断
if 支持对变量进行简单比较,常用变量包括:
-
$args:查询参数字符串(如a=1&b=2) -
$arg_xxx:指定参数值(如$arg_version获取?version=2中的2) -
$http_x_forwarded_for、$http_user_agent等 Header 变量 -
$host、$request_uri、$scheme等内置变量
常见分流场景写法示例
以下写法都放在 location 块内,注意 if 块中只能使用有限指令(如 return、rewrite、set、proxy_pass 不允许直接写):
-
按参数分流到不同 upstream:
if ($arg_env = "prod") { rewrite ^(.*)$ /prod$1 break; }
再配合location /prod { proxy_pass http://prod_backend; } -
按 User-Agent 区分移动端:
if ($http_user_agent ~* "(mobile|android|iphone)") { set $is_mobile "1"; }
后续可用$is_mobile控制 rewrite 或 header 注入 -
按请求头灰度路由:
if ($http_x_release_flag = "v2") { rewrite ^(.*)$ /v2$1 break; }
必须避开的坑
if 在 location 中不是“编程 if”,而是“配置阶段条件匹配”,有硬性限制:
- 不支持嵌套
if,也不支持&&、||多条件(要用正则~*组合匹配) -
proxy_pass、fastcgi_pass不能直接写在if里(会报错),需配合rewrite + location拆解 - 变量未定义时值为空字符串,
$arg_xxx不存在时也是空,比较要写全(如用= ""判空) - 重写路径时注意
break和last行为差异:前者终止当前 location 匹配,后者重新匹配 location
更稳的替代方案建议
如果分流逻辑稍复杂(比如多条件组合、需要 fallback),推荐:
- 用
map指令预定义变量(支持正则、默认值、多条件映射),再在location中引用 —— 更高效、更安全 - 静态资源或简单跳转用
try_files+ 文件存在判断 - 真正动态路由交给上游服务(如 API 网关),Nginx 只做透传或轻量标记











