【问题标题】:How to control NGINX 'Location' directive matching order?如何控制 NGINX 'Location' 指令匹配顺序?
【发布时间】:2012-01-16 06:43:54
【问题描述】:

我正在尝试优化我的“位置”指令,但找不到确定是否尝试特定位置匹配的好方法。在 location 块中使用 echo 在这里没有帮助。

The NGINX ngx_http_core_module documentation 有点混乱。

要使用正则表达式,必须使用前缀:

  1. ~ 用于区分大小写的匹配

  2. ~* 用于不区分大小写的匹配

比赛是如何进行的:

  1. 带有 = 前缀的指令与查询完全匹配。如果找到,则停止搜索。

  2. 所有剩余的指令都带有常规字符串。如果此匹配使用了^~ 前缀,则停止搜索。

  3. 正则表达式,按照它们在配置文件中定义的顺序。

  4. 如果 #3 产生匹配,则使用该结果。否则,使用 #2 中的匹配项。

这里的数字 2 表示“常规字符串”,但随后表示它可以与 ^~ 前缀一起使用。 ~ 不是暗示正则表达式吗?如果不是,它如何确定什么是非正则表达式?

具体来说,我想要以下内容:

  1. 直接提供文字 /assets 之外的任何内容。停止搜索。

  2. 通过快速 CGI STOP SEARCH 提供与 RegExp \.php$|/$ 匹配的任何内容。

  3. 直接通过文字/提供其他所有内容

这样,只有/ 匹配从资产外部提供的非动态文件的尝试。

我有:

location ^~ /assets {}      # search-terminating literal? or regex?
location ~ \.php$|/$ {}
location / {}               # is this match always attempted?

从文档看来,实际顺序似乎是 1-3-2,始终运行文字 / 匹配。是的,这种优化不会对实际性能产生任何影响,但我只是想澄清一些歧义。

【问题讨论】:

    标签: nginx url-rewriting nginx-location


    【解决方案1】:

    来自维基:

    location  = / {
      # matches the query / only.
      [ configuration A ] 
    }
    location  / {
      # matches any query, since all queries begin with /, but regular
      # expressions and any longer conventional blocks will be
      # matched first.
      [ configuration B ] 
    }
    

    所以,这将首先匹配: location ~ \.php$ {}

    即使资产是由location / {} 提供的

    在 php 块中,您还希望在传递给 fastcgi 之前防止恶意上传:

    if ($uri ~* "^/uploads/") {
      return 404;
    }
    

    如您所见,nginx 的工作方式与您预期的略有不同。

    【讨论】:

    • 我仍然不清楚为什么首先匹配正则表达式。授予没有“=”指令。接下来是“所有剩余的带有常规字符串的指令”。 '/' 是一个常规字符串,应该在任何正则表达式之前匹配。整个 strings-then-regex 是 nginx 似乎在这里做的一个手持隐式优化,这使得很难确定评估的真实顺序。我认为 apache/iptables 等可以通过以定义为 if/else-if/else 块的相同顺序进行可预测的处理来正确处理。没有任何隐含的“更多/更少”特定规则。
    • 对,这对 nginx 肯定有点混乱,尤其是 nginx 的 if 应该只用于 rewrite/return。我认为他们正在努力简化这一点。对于您的情况,它将像这样工作: 1. php regex 检查是否匹配 2. / 任何静态内容。
    • 您的订单有误。首先将 /assets 规则作为字符串的全部意义在于避免在每个请求上运行 php 正则表达式的开销。事实上,我想在不通过 FCGI 的情况下提供像 assets/docs/example.php 这样的东西。我目前正在运行此设置,并且正则表达式不会捕获 example.php。它的顺序为 ^~ /assets, /, ~ \.php$|/$
    • 您可以在 nginx 上的某个地方询问是否可以完全这样做。另请查看try_files。不过,在 Apache 上使用 nginx 可以提高性能 :)
    • 是的,我知道,正如我在 OP 中指出的那样,这实际上与性能无关,而是与理解匹配规则的清晰度有关。它们的隐含性/复杂性使它们更难维护、容易出错,因此安全性较低
    猜你喜欢
    • 2016-06-26
    • 2022-01-17
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 2023-01-26
    相关资源
    最近更新 更多