【问题标题】:How can I have same rule for two locations in NGINX config?如何在 NGINX 配置中为两个位置设置相同的规则?
【发布时间】:2016-05-21 03:04:05
【问题描述】:

如何在 NGINX 配置中为两个位置设置相同的规则?

我已经尝试了以下

server {
  location /first/location/ | /second/location/ {
  ..
  ..
  }
}

但是 nginx reload 抛出了这个错误:

nginx: [emerg] invalid number of arguments in "location" directive**

【问题讨论】:

    标签: nginx nginx-location


    【解决方案1】:

    试试

    location ~ ^/(first/location|second/location)/ {
      ...
    }
    

    ~ 表示对 url 使用正则表达式。 ^ 表示从第一个字符开始检查。这将查找/,然后是其中一个位置,然后是另一个/

    【讨论】:

    • 注意:如果这种情况经常发生(如数千次),则会因正则表达式匹配而导致性能损失。匹配的顺序也大不相同。在很多“小”情况下,它的行为会像你想要的那样,但这是需要注意的。我个人希望 Nginx“位置”支持多个“=”条件,而不是依赖于正则表达式规则。
    • 恕我直言,这应该更有效: location ~ (patternOne|patternTwo){ ... }
    • 这个解决方案对我不起作用;但是@stamster 的评论确实如此;我正在运行nginx/1.13.2
    • 如果您需要proxy_pass 工作,请查看此答案:stackoverflow.com/a/46625656/1246870
    • 当原始 URL 以无斜杠结尾时,这对我不起作用
    【解决方案2】:

    另一种选择是使用包含文件在两个前缀位置重复规则。由于前缀位置在配置中与位置无关,因此在您稍后添加其他正则表达式位置时,使用它们可以避免一些混乱。尽可能避免使用正则表达式位置将有助于您的配置顺利扩展。

    server {
        location /first/location/ {
            include shared.conf;
        }
        location /second/location/ {
            include shared.conf;
        }
    }
    

    这是一个示例 shared.conf:

    default_type text/plain;
    return 200 "http_user_agent:    $http_user_agent
    remote_addr:    $remote_addr
    remote_port:    $remote_port
    scheme:     $scheme
    nginx_version:  $nginx_version
    ";
    

    【讨论】:

    • 能否添加shared.conf 示例和位置?
    • 我添加了一个示例 shared.conf 文件。您可以使用 shared.conf 的绝对路径或将其放在您的 nginx 目录中。在这种情况下,它只包含几个指令。
    【解决方案3】:

    正则表达式和包含文件都是很好的方法,我经常使用它们。但另一种选择是使用“命名位置”,这在许多情况下都是有用的方法——尤其是更复杂的情况。 official "If is Evil" page 基本上显示了以下作为做事的好方法:

    error_page 418 = @common_location;
    location /first/location/ {
        return 418;
    }
    location /second/location/ {
        return 418;
    }
    location @common_location {
        # The common configuration...
    }
    

    这些不同的方法各有优缺点。正则表达式的一大优势是您可以捕获部分匹配项并使用它们来修改响应。当然,您通常可以通过在原始块中设置变量或使用map 来使用其他方法获得类似的结果。正则表达式方法的缺点是,如果您想匹配各种位置,它可能会变得笨拙,而且low precedence of a regex 可能不适合您想要匹配位置的方式——更不用说正则表达式显然会对性能产生影响在某些情况下。

    包含文件的主要优点(据我所知)是它可以更灵活地确定您可以包含的内容 - 例如,它不必是完整的位置块。但它也只是主观上比命名位置有点笨拙。

    另请注意,您可以在类似情况下使用一个相关的解决方案:嵌套位置。这个想法是,您将从一个非常一般的位置开始,对几个可能的匹配项应用一些通用配置,然后为要匹配的不同类型的路径设置单独的嵌套位置。例如,这样做可能会很有用:

    location /specialpages/ {
        # some config
        location /specialpages/static/ {
            try_files $uri $uri/ =404;
        }
        location /specialpages/dynamic/ {
            proxy_pass http://127.0.0.1;
        }
    }
    

    【讨论】:

    • 注意:“别名”指令不能在指定位置内使用。
    • 最好在返回 418 error_page 上添加一个解释,这有点令人困惑,但基本上这是使用错误页面作为 goto 块,418 错误代码是“It's a teapot”开玩笑,它是少数可以使用的安全代码之一
    【解决方案4】:

    这是一种简短但有效且经过验证的方法:

    location ~ (patternOne|patternTwo){ #rules etc. }

    因此,一个人可以很容易地拥有多个模式,使用简单的管道语法指向相同的位置块/规则。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-11
      • 2015-06-11
      • 2017-01-19
      • 1970-01-01
      • 2022-01-13
      • 2016-05-30
      • 1970-01-01
      • 2016-02-27
      相关资源
      最近更新 更多