<Location> 和部分 non-existing 目录?

<Location> and partially non-existing directory?

在 Apache 2.2 和 2.4 中,<Location /foo> 指令出现奇怪的行为并请求 URL http://example.com/foo/non-existing 不匹配。

假设我的配置是:

<VirtualHost *:80>
   DocumentRoot "/var/www/apache.test"
   ServerName apache.test

   <Directory "/var/www/apache.test">
       Options Indexes FollowSymLinks
       AllowOverride None
       Order allow,deny
       Allow from all

       # Catch non-existing resources with index.php:
       RewriteEngine On
       RewriteCond %{REQUEST_FILENAME} -s [OR]
       RewriteCond %{REQUEST_FILENAME} -l [OR]
       RewriteCond %{REQUEST_FILENAME} -d
       RewriteRule ^.*$ - [L]
       RewriteCond %{REQUEST_URI}:: ^(/.+)/(.*)::$
       RewriteRule ^(.*) - [E=BASE:%1]
       RewriteRule ^(.*)$ %{ENV:BASE}/index.php [L]
   </Directory>

   <Location "/">
       Header set X-All "true"
   </Location>

   <Location "/foo">
       Header set X-Foo "true"
   </Location>
</VirtualHost>

DocumentRoot目录/var/www/apache.test有以下内容:

/var/www/apache.test
├── bar
│   └── baz
├── foo
│   └── qux
└── index.php

请注意,/foo 目录实际存在于 DocumentRoot 中,而目录 /foo/non-existing 不存在。

测试各种 URLs 使用:curl -D - http://apache.test/ -o /dev/null -s | grep -F "X-"

我得到以下结果:

URL                    | X-All? | X-Foo?
-----------------------|--------|-------
/                      |      X |
/bar/                  |      X |
/bar/baz/              |      X |
/bar/non-existing/     |      X |
/non-existing/         |      X |
/foo/                  |      X |      X
/foo/qux/              |      X |      X
/foo/non-existing/     |      X |
/foo/qux/non-existing/ |      X |

我认为 <Location "/foo"> 会为 http://apache.test/foo/* 的任何请求添加一个 header。

我得到 <Directory> 用于文件系统项,<Location> 用于动态 URL。所以我也尝试使用 <Directory><Location> 来涵盖所有情况:

<VirtualHost *:80>
   DocumentRoot "/var/www/apache.test"
   ServerName apache.test

   <Directory "/var/www/apache.test">
       Options Indexes FollowSymLinks
       AllowOverride None
       Order allow,deny
       Allow from all

       # Catch non-existing resources with index.php:
       RewriteEngine On
       RewriteCond %{REQUEST_FILENAME} -s [OR]
       RewriteCond %{REQUEST_FILENAME} -l [OR]
       RewriteCond %{REQUEST_FILENAME} -d
       RewriteRule ^.*$ - [L]
       RewriteCond %{REQUEST_URI}:: ^(/.+)/(.*)::$
       RewriteRule ^(.*) - [E=BASE:%1]
       RewriteRule ^(.*)$ %{ENV:BASE}/index.php [L]

       Header set X-AllDir "true"
   </Directory>
   <Location "/">
       Header set X-AllLoc "true"
   </Location>

   <Directory "/var/www/apache.test/foo">
       Header set X-FooDir "true"
   </Location>
   <Location "/foo">
       Header set X-FooLoc "true"
   </Location>
</VirtualHost>

我得到以下结果:

URL                    | X-AllDir? | X-AllLoc? | X-FooDir? | X-FooLoc?
-----------------------|-----------|-----------|-----------|----------
/                      |         X |         X |           |
/bar/                  |         X |         X |           |
/bar/baz/              |         X |         X |           |
/bar/non-existing/     |         X |         X |           |
/non-existing/         |         X |         X |           |
/foo/                  |         X |         X |         X |         X
/foo/qux/              |         X |         X |         X |         X
/foo/non-existing/     |         X |         X |           |
/foo/qux/non-existing/ |         X |         X |           |

我也试过只有一个 <Location> 专用于 "/foo/non-existing/":

<VirtualHost *:80>
   DocumentRoot "/var/www/apache.test"
   ServerName apache.test

   <Directory "/var/www/apache.test">
       Options Indexes FollowSymLinks
       AllowOverride None
       Order allow,deny
       Allow from all

       # Catch non-existing resources with index.php:
       RewriteEngine On
       RewriteCond %{REQUEST_FILENAME} -s [OR]
       RewriteCond %{REQUEST_FILENAME} -l [OR]
       RewriteCond %{REQUEST_FILENAME} -d
       RewriteRule ^.*$ - [L]
       RewriteCond %{REQUEST_URI}:: ^(/.+)/(.*)::$
       RewriteRule ^(.*) - [E=BASE:%1]
       RewriteRule ^(.*)$ %{ENV:BASE}/index.php [L]
   </Directory>

   <Location "/foo/non-existing">
       Header set X-FooNonExisting "true"
   </Location>
</VirtualHost>

但是http://apache.test/foo/non-existing还是不会return X-FooNonExisting header.

在我看来,Apache 以某种方式无法将请求与 /foo/non-existing/ 匹配,因为请求的资产既针对现有目录 ("/foo") 又针对 virtual-subdir ("non-existing").

我的最终目标是在所有 HTTP 响应(对于这个 VirtualHost)中设置一个给定的 header,但那些响应请求的 http://example.com/foo/qux/non-existing/*.

这是因为倒数第二个重写不匹配但最后一次重写匹配,导致在 mod_headers 过滤器运行时您的请求不再针对 /foo/ 吗?