Nginx 的 if 仅适用于 server 块顶层的轻量路由判断,用于请求特征识别、快速拒绝或简单分流,须遵循收口、预筛、避嵌套、禁重写等约束;所有判断应集中于 server 开头,用内置变量初步分流,通过 set 缓存特征值,避免 location 内嵌套 if 导致上下文异常,多条件组合宜用单正则预筛+变量组合判断,高频分支前置,优先使用 location、return、map、try_files 等更稳定原生指令替代 if。

Nginx 的 server 块中可以用 if 做轻量路由判断,但不是写业务逻辑的地方——它只适合做请求特征识别、快速拒绝或简单分流,且必须严格遵循收口、预筛、避嵌套、禁重写等约束。
统一收口在 server 顶层,不进 location 嵌套
if 只能在 server 或 location 块里用,但在 location 内嵌套 if 会触发上下文重建,导致 proxy_pass、rewrite 行为异常。所有判断应集中到 server 块开头:
- 用
$host、$scheme、$request_method等内置变量做初步分流 - 通过
set提前提取关键特征,比如:set $route_type "default";<br>if ($host ~* "^api\.") { set $route_type "api"; }<br>if ($request_uri ~* "^/admin/") { set $route_type "admin"; } - 后续所有分支都基于
$route_type判断,避免重复解析
用正则预筛 + 变量缓存降复杂度
多个条件组合(如“微信浏览器 + 支付路径”)不要层层 if 嵌套,而是用单条正则一次性捕获特征:
if ($http_user_agent ~* "(Mobile|Android|iPhone).*MicroMessenger") { set $ua_wechat_mobile "1"; }if ($request_uri ~* "^/pay/") { set $uri_is_pay "1"; }- 再统一判断:
if ($ua_wechat_mobile = "1" && $uri_is_pay = "1") { return 302 https://pay.example.com$request_uri; } - 注意:Nginx 不支持
&&运算符,这里依赖的是短路求值逻辑——两个变量都非空才生效
高频分支前置,失败快速终止
if 按顺序执行,第一个为真即停止。把最常命中的条件放最前面:
-
if ($request_method = GET) { ... }(占比最高) if ($request_method = POST) { ... }-
if ($request_method !~ ^(GET|POST|HEAD)$) { return 405; }(兜底拦截非法方法) - 对恶意 UA、非法 referer、缺失 token 等场景,优先用
return 403或return 444快速切断,不留给下游处理
能不用 if 就别用,优先选更稳的原生指令
if 是最后手段。多数场景有更可靠替代:
- 按路径分发 → 用
location ^~ /api/或location ~ \.php$ - 强制 HTTPS → 用
listen 80; return 301 https://$host$request_uri; - 根据 Header 或 Cookie 选 upstream → 用
map预定义变量,零运行时开销 - ThinkPHP 等框架入口统一 → 用
try_files $uri $uri/ /index.php?$query_string;,比if (!-f $request_filename)更安全


















