Apache 如何合并多个匹配的 Location 部分

Lor*_*igs 43 apache-2.2

我正在研究一些基本的 apache 配置,但我不明白 apache 如何<Location>在其中几个与传入的请求 URL 匹配时合并不同的部分。当涉及到相同类型的多个匹配部分的顺序/优先级时,其“如何合并部分”一章中的apache 文档有点令人困惑。

例如,想象下面的apache配置(忽略实际内容是否有意义,我只对每个规则/部分的应用顺序感兴趣):

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>
Run Code Online (Sandbox Code Playgroud)

现在,如果客户端向 发出请求/sub/foobar,将应用于此请求的最终配置是哪个?

应用的配置是否等同于:

# All the directives contained in all the matchin Locations in declaration order
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order allow,deny
Order deny,allow
Require valid-user
Satisfy all
Run Code Online (Sandbox Code Playgroud)

或者可能

# same as above, but with longest matching path last
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order deny,allow
Require valid-user
Satisfy all
Order allow,deny
Run Code Online (Sandbox Code Playgroud)

或者完全不同的东西。

谢谢你的帮助,我真的很困惑。

Tom*_*Tom 55

合并的顺序比较复杂,很容易被异常抓到……apache doc是“ How the Sections are merge

根据该文档,部分合并的顺序是通过按照在配置文件中遇到的顺序处理每个匹配类型的所有匹配条目来完成的,最后一个匹配获胜。(<Directory> 除外,它按路径特异性顺序处理)。

类型的顺序是DirectoryDirectoryMatchFiles,和最后Location。较晚的匹配会覆盖较早的匹配。(*ProxyPass 和 Alias 的处理方式再次不同,请参阅最后的注释)

这些规则有几个重要的例外,适用于在 <Location> 部分中使用 ProxyPass 和 ProxyPass。(见下文)

因此,从上面的示例中,使用以下配置请求http://somehost.com/sub/foobar

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>
Run Code Online (Sandbox Code Playgroud)

它将累积以下指令......

  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
  Order allow,deny
  Order deny,allow
  Require valid-user
  Satisfy all   
Run Code Online (Sandbox Code Playgroud)

后面的匹配消除了以前的重复项,结果是;

  ProxyPass http://backend.com/
  Order deny,allow
  Require valid-user
  Satisfy all   
Run Code Online (Sandbox Code Playgroud)

说明
稍后匹配会覆盖较早的匹配,但<Directory>匹配的处理顺序除外:最短的目录组件到最长的。

因此,例如, 无论这些指令在配置中指定的顺序如何,
<Directory /var/web/dir>
都将在之前处理
<Directory /var/web/dir/subdir>
,并且更具体的匹配获胜。

任何匹配的Location指令将始终覆盖先前匹配的Directory指令。

基本思想是,对于像GET /some/http/request.html内部这样的请求,它将通过 转换为文件系统中的一个位置AliasScriptAlias或者转换为DocumentRoot它匹配的 VirtualHost下的正常文件位置。

因此,请求将具有以下用于匹配的属性:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

然后 Apache 将依次应用所有Directory匹配项,按照目录特定性的顺序,从配置中依次应用DirectoryMatch,然后依次应用,Files最后Location按照遇到它们的顺序进行匹配。

所以Locationoverrides Files,它覆盖DirectoryMatch,路径匹配Directory的优先级最低。因此,在上面的示例中,请求/sub/foobar将按顺序匹配前 3 个位置,因此最后一个因指令冲突而获胜。

(您是对的,从文档中不清楚一些边缘情况是如何解决的,任何allow from *类型指令都可能连接到关联的Order allow,deny,但我没有测试它。如果您匹配Satisfy Any但会发生什么以前收集了一个Allow from *...)

关于 ProxyPass 和 Alias 的有趣说明

只是很烦人,ProxyPass并且Alias似乎在另一个方向上工作...... ;-) 它基本上击中了第一场比赛,然后停止并使用它!

Ordering ProxyPass Directives

The configured ProxyPass and ProxyPassMatch rules are 
checked in the order of configuration. 
The first rule that matches wins. So
usually you should sort conflicting ProxyPass rules starting with the
longest URLs first. Otherwise later rules for longer URLS will be
hidden by any earlier rule which uses a leading substring of the URL.
Note that there is some relation with worker sharing.

For the same reasons exclusions must come before the general 
ProxyPass directives.
Run Code Online (Sandbox Code Playgroud)

所以基本上,必须指定 Alias 和 ProxyPass 指令,首先是最具体的;

Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo"     "/srv/www/common/foo"
Run Code Online (Sandbox Code Playgroud)

ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On
Run Code Online (Sandbox Code Playgroud)

但是,正如@orev 指出的那样。您可以在 Location 指令中使用 ProxyPass 指令,因此 Location 中更具体的 ProxyPass 将击败之前找到的任何 ProxyPass。

  • 关于`ProxyPass` _“向另一个方向工作”_,只有当它们在`&lt;Location&gt;` 之外时才是正确的。在 `&lt;Location&gt;` 中,遵循合并 `&lt;Location&gt;` 的规则,这意味着您希望最不具体的 `&lt;Location&gt;` 指令_before__更具体的指令。这允许更具体的指令覆盖不太具体的指令。每个 `&lt;Location&gt;` 只能有一个 `ProxyPass`。 (4认同)
  • 感谢您标记有关订购 ProxyPass 指令的警告。让我免了很多头痛 (3认同)