Nginx 修饰符 `=` 和 `^~` 之间到底有什么区别?

Nginx 修饰符 `=` 和 `^~` 之间到底有什么区别?

=据我所知,^~都是普通字符串前缀修饰符(既不是'reg-exp' 修饰符)。两者都只允许精确匹配(否则将被视为不匹配)。如果发现精确匹配,则两者都会停止进一步的匹配过程,并立即提供随附的“位置”。

那么这两个修饰符有什么区别呢?

答案1

据我所读/所理解,= 和 ^~ 都是普通字符串前缀修饰符(都不是“reg-exp”修饰符)。

  • =是精确匹配,而不是前缀匹配
  • ^~是一种“优先”前缀匹配,其优先级高于正则表达式匹配。换句话说,它与标准前缀位置相同,location /something唯一的区别是,如果它与 URI 匹配,则不会搜索正则表达式位置。

两者都只允许完全匹配(否则将被视为不匹配)。

  • =仅允许精确匹配,location = /foo仅被视为匹配 URI /foo(或/foo?some=arg),而不匹配其他任何内容,例如foobar不会匹配它
  • ^~允许前缀匹配,例如location ^~ /foo匹配/foo/foobar/fooanything

如果发现完全匹配,则停止进一步的匹配过程,并立即提供附带的“位置”。

那么这两个修饰符有什么区别呢?

如上所述,仅限=精确匹配,只有一个 URI 基础可匹配,并且优先于其他匹配类型。

^~无限可能的匹配。这是两者之间的关键区别。

完全匹配的(=)是性能最高效的匹配类型. 尽可能使用它:

location = /foo/bar/ { return 301 /foo; }

优于location ~ ^/foo/bar$ { return 301 /foo; }

如果您想拒绝对特定目录的访问,优先前缀匹配也很有意义,因为它不涉及正则表达式评估:

location ^~ /foo/ {
    deny all;
}

将拒绝/foo/目录内的任何内容,而不仅仅是/foo/URI。

回顾一下:

# matching URIs: /foo, /foo?some=1, etc.
# fastest matching of all, highest priority
location = /foo { ... }

# matching URIs: /foo, /foob, /foob?some=1, /foobar, /foo[...]
# second fasted matching of all, the second highest priority
location ^~ /foo { ...}

答案2

更新

感谢@danila-vershinin 指出这一点,但=实际上并没有定义前缀,而只是定义了精确匹配。请参阅他的回答以获得更完整/正确的答案。

以下是原始答案

=如果您只有一个位置,那么您是对的,使用或都没关系^~。当您有多个位置时,就会出现差异,不同的修饰符会影响最终匹配的顺序。

来自文档

除非使用修饰符,否则正则表达式的优先级更高^~。在前缀字符串中,NGINX Plus 选择最具体的一个(即最长和最完整的字符串)。选择处理请求的位置的具体逻辑如下:

  1. 根据所有前缀字符串测试 URI。
  2. (等号)修饰符=定义 URI 和前缀字符串的精确匹配。如果找到精确匹配,则搜索停止。
  3. 如果^~(插入符号波浪号) 修饰符添加最长匹配的前缀字符串,则不会检查正则表达式。
  4. 存储最长匹配的前缀字符串。
  5. 根据正则表达式测试 URI。
  6. 当找到第一个匹配的正则表达式时停止处理并使用相应的位置。
  7. 如果没有正则表达式匹配,则使用存储的前缀字符串对应的位置。

基本上,= /test如果您想匹配精确的路径/test,那么很有用,在这种情况下,所有进一步的处理(正则表达式)都会被省略。

如果未找到精确匹配项,则=^~均为字首匹配,并从所有这些位置中选择最长的匹配。如果该匹配具有修饰符,^~则将立即使用它,否则将首先检查正则表达式。

在具体示例中,如果您有位置= /test并请求路径/test/bla.html,则首先将检查所有其他正则表达式,并且只有当没有匹配时才会= /test使用 。相反,如果您有^~ /test并请求/test/bla.html,则将使用此正则表达式,即使有匹配 的正则表达式也是如此*.html

附言

请注意,只有最长匹配前缀在这里很重要。如果您有两个位置:= /test^~ /test/bla并且要求/test/bla/x.html,那么^~ /test/bla就是使用的,并且由于它有^~,所以不会检查正则表达式。如果位置是^~ /test= /test/bla,那么=就是最长的,所以在这种情况下将检查正则表达式(并且^~ /test完全忽略)。

相关内容