Nginx的rewrite指令本身不支持条件判断,需配合if指令使用;if支持变量比较、正则匹配及文件/目录存在性检查,但存在性能与行为风险,推荐优先使用try_files或location精确匹配替代。

Nginx 的 rewrite 指令本身不支持条件判断,真正做条件判断的是 if 指令,它必须配合 rewrite、return 或 set 等指令使用。直接在 rewrite 后面写条件是无效的。
if 指令的基本写法
if 是 Nginx 的一个“看似简单、实则危险”的指令,语法为:if (condition) { ... }
括号内是判断表达式,支持变量、比较运算符(=、!=、~、!~、~*、!~*)、正则匹配和文件/目录存在性检查(-f、-d、-e、-x)。
-
=和!=:字符串精确匹配(区分大小写) -
~:区分大小写的正则匹配 -
~*:不区分大小写的正则匹配 -
!~和!~*:取反匹配 -
-f:检查是否为普通文件且存在 -
-d:检查是否为目录且存在 -
-e:检查文件或目录是否存在(通用) -
-x:检查是否为可执行文件
常见 rewrite 条件判断场景
实际中常把 if 和 rewrite 组合使用,实现按需重写:
- 根据请求域名跳转:
if ($host = 'www.example.com') { rewrite ^/(.*)$ https://example.com/$1 permanent; } - 屏蔽特定 User-Agent:
if ($http_user_agent ~* "wget|curl") { return 403; } - 对非静态资源启用重写(排除图片、CSS、JS):
if ($request_uri !~ \.(js|css|png|jpg|gif|ico)$) { rewrite ^/(.*)$ /index.php?path=$1 last; } - 检查文件不存在时再重写(典型伪静态):
if (!-f $request_filename) { rewrite ^/(.*)$ /index.php?$1 last; }
需要注意的关键限制
if 在 location 块中使用时,有多个隐含行为容易引发问题:
- 所有
if块内的指令(包括rewrite)都会在每次请求时重新执行,性能开销比location匹配高 -
if中的rewrite会重置 URI,后续location匹配将基于新 URI 进行 -
if不支持嵌套,也不能用于 server 块顶层(除非配合server_name等有限变量) - 部分变量(如
$args、$query_string)在if内可能未被正确解析,建议用$arg_XXX直接取参数 - 官方文档明确警告:尽量避免用
if做复杂逻辑,优先考虑try_files或更精准的location匹配
更安全的替代方案
多数场景下,可以用更高效、更可靠的方式代替 if + rewrite:
- 用
try_files实现“文件存在则返回,否则转发”:try_files $uri $uri/ /index.php?$query_string; - 用多个
location精确匹配路径或后缀:location ~ \.php$ { ... }、location ^~ /static/ { ... } - 用
map指令预定义变量,再在rewrite或return中引用,避免运行时判断
不复杂但容易忽略。


















