Nginx 的 if 指令是属于 rewrite 模块的,所以对于 if 来讲,会和其他的 rewrite 模块执行全部执行完之后再进行下一阶段。如果 if 指令的结果是 match 的,那么 if 会创建一个内嵌的 location 块,只有这里面的 content 处理指令(NGX_HTTP_CONTENT_PHASE 阶段)会执行。
Nginx 的 if 指令被认为是 “邪恶” 的,就和 C 语言 的 goto
一样。甚至官方有一篇 If is Evial 来警告你不要使用 if
。但有时候 if 还是非常有用的,如果掌握了它的原理,在合适的地方正确使用 if,会让事情更简单一些。当然前提是你真正知道自己在做什么,就和 goto 一样。
if 指令用来判断条件为 true 时要执行的指令,条件 false 时不执行相应的指令,if 指令只能用在 server、location内。
if (condition) { ... }
condition 可以是如下类型:
if 指令不支持多条件、不支持嵌套、不支持 else,与常见的条件表达式不同的是if指令等值比较使用单个等号=而不是双等号 ==。
if 是一个危险的指令,除了当判断一个变量的值时必须使用 if 的场景,其它情况使用 if 时都需要仔细思考可能会出现的执行结果,能不用就不用,稍不小心就会有意想不到的执行结果。我们大多数人都按过程化顺序编程思路来判断结果,但 nginx 还有很多上下文环境需要考虑。
比较安全的用法是满足 if 条件时只执行 return 指令。{} 内尽量只使用下面两种指令。否则,nginx 可能不会按照你预想顺序执行,严重的情况下 nginx 会段错误崩溃。
return ...;
rewrite ... last;
还有就是尽量别在 location 中使用 if,在 server 中使用 if 相对会安全些。
如果要在 location 中使用 if,最好用如下模版格式:
location / {
error_page 418 = @other;
recursive_error_pages on;
if ($something) {
return 418;
}
# some configuration
...
}
location @other {
# some other configuration
...
}
nginx 不支持下面这样的多条件 if:
if ($request_method = POST && $http_cookie ~* "CCCC=.+(?:;|$)")
变通办法是:
if ($request_method = POST) {
set $test P;
}
if ($http_cookie ~* "CCCC=.+(?:;|$)" ) {
set $test "${test}C";
}
if ($test = PC) {
#rewrite rule goes here.
}
正则 | 描述 |
---|---|
== | 等值比较 |
~ | 与指定正则表达式模式匹配时返回 “真”,判断匹配与否时区分字符大小写; |
~* | 与指定正则表达式模式匹配时返回 “真”,判断匹配与否时不区分字符大小写 |
!~ | 与指定正则表达式模式不匹配时返回 “真”,判断匹配与否时区分字符大小写 |
!~* | 与指定正则表达式模式不匹配时返回 “真”,判断匹配与否时不区分字符大小写 |
正则 | 描述 |
---|---|
-f, !-f | 判断指定的路径是否为存在且为文件; |
-d, !-d | 判断指定的路径是否为存在且为目录; |
-e, !-e | 判断指定的路径是否存在,文件或目录均可; |
-x, !-x | 判断指定路径的文件是否存在且可执行; |
遇到 break 就跳出,后面的指令不在执行,比如:
if (!-f $reque_filename){
set $id = 1; #有效的指令
break;
limit_rate 10k; #无效的指令
}
完成对请求的处理。直接向客户端返回响应状态码。比如:
return code URL ;
return [text];
参数解释如下:
参数 | 描述 |
---|---|
code | 返回给客户端的 HTTP 状态码 |
URL | 返回给客户端的 URL 地址 |
text | 返回给客户端的响应体内容,支持变量。 |
设置变量,语法如下:
set $id = 2
Nginx 的 if 指令被认为是 “邪恶” 的,就和 C 语言的 goto
一样。甚至官方有一篇 If is Evial 来警告你不要使用 if
。但有时候 if 还是非常有用的,如果掌握了它的原理,在合适的地方正确使用 if,会让事情更简单一些。当然前提是你真正知道自己在做什么,就和 goto 一样。
if 指令用来判断条件为 true 时要执行的指令,条件 false 时不执行相应的指令,if 指令只能用在 server、location内。