Nginx if指令

Nginx if指令

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内。

Nginx if指令详解

语法

if (condition) { ... }

说明

condition 可以是如下类型:

  • 变量名,如果变量的值是空字符串或者 0 表示 false
  • 变量使用 “=” 和 “!=” 来跟字符串比较
  • 可以是正则表达式
  • 检查文件是否存在使用 “-f” 和 “!-f”
  • 检查目录是否存在使用 “-d” 和 “!-d”
  • 检查文件、目录、符号链接是否存在使用 “-e” 和 “!-e”
  • 检查是否是可执行文件使用 “-x” 和 “!-x”

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. }

Nginx if比较

正则匹配

正则 描述
== 等值比较
~ 与指定正则表达式模式匹配时返回 “真”,判断匹配与否时区分字符大小写;
~* 与指定正则表达式模式匹配时返回 “真”,判断匹配与否时不区分字符大小写
!~ 与指定正则表达式模式不匹配时返回 “真”,判断匹配与否时区分字符大小写
!~* 与指定正则表达式模式不匹配时返回 “真”,判断匹配与否时不区分字符大小写

文件及目录匹配

正则 描述
-f, !-f 判断指定的路径是否为存在且为文件;
-d, !-d 判断指定的路径是否为存在且为目录;
-e, !-e 判断指定的路径是否存在,文件或目录均可;
-x, !-x 判断指定路径的文件是否存在且可执行;

Nginx if关键字

break

遇到 break 就跳出,后面的指令不在执行,比如:

if (!-f $reque_filename){ set $id = 1; #有效的指令 break; limit_rate 10k; #无效的指令 }

return

完成对请求的处理。直接向客户端返回响应状态码。比如:

return code URL ; return [text];

参数解释如下:

参数 描述
code 返回给客户端的 HTTP 状态码
URL 返回给客户端的 URL 地址
text 返回给客户端的响应体内容,支持变量。

set

设置变量,语法如下:

set $id = 2

Nginx if指令总结

Nginx 的 if 指令被认为是 “邪恶” 的,就和 C 语言的 goto 一样。甚至官方有一篇 If is Evial 来警告你不要使用 if 。但有时候 if 还是非常有用的,如果掌握了它的原理,在合适的地方正确使用 if,会让事情更简单一些。当然前提是你真正知道自己在做什么,就和 goto 一样。

if 指令用来判断条件为 true 时要执行的指令,条件 false 时不执行相应的指令,if 指令只能用在 server、location内。