我有一个看似简单的问题。我想将一组配置指令应用于单个文件(在本例中myfile.html
为 DocumentRoot)。可能还有包含的子目录myfile.html
,这些应该不是获取配置。我也想这样做没有使用Location
或LocationMatch
。
我想出了以下
DocumentRoot "/home/amoe/opt/httpd/htdocs"
<DirectoryMatch "^/home/amoe/opt/httpd/htdocs$">
<Files "myfile.html">
ExpiresActive on
ExpiresDefault A10
</Files>
</DirectoryMatch>
但是,Expires
请求时不会设置标头/myfile.html
。在后面添加斜杠DirectoryMatch
似乎没有什么区别。
你可以假设我想这样做,不是Location
出于学术原因。(编辑:另外,引用文档,当尝试限制对文件系统中的对象的访问时,切勿使用这一点很重要。)
答案1
我发现使这个工作的唯一方法是使用以下命令:
<DirectoryMatch ^/home/amoe/opt/httpd/htdocs/[^/]+$>
<Files "test.html">
ExpiresActive on
ExpiresDefault A10
</Files>
</DirectoryMatch>
我相信[^/]+
不需要额外的操作就可以使其工作,请参阅下面的完整解释,了解我如何得出这个结论,因此我相信这是 Apache 中的一个错误。
以下所有内容均基于运行 Apache 2.4.23 的 Ubuntu 16.04.1 LTS 环境,测试文件位于以下位置:
/path/test/test.html
/path/test/noheader-test.html
/path/test/child/test.html
/path/test/child/grandchild/test.html
首先,我尝试了许多不同的正则表达式变体,但都无法匹配:
<DirectoryMatch ^/path/test$>
<DirectoryMatch ^/path/test/$>
<DirectoryMatch /path/test/$>
<Directory ~ ^/path/test$>
<Directory ~ ^/path/test/$>
<Directory ~ /path/test/$>
然而我发现如果省略 EOL 锚点($
),那么它会匹配:
<DirectoryMatch ^/path/test/>
<Files "test.html">
ExpiresActive on
ExpiresDefault A10
</Files>
</Directory>
然而这当然test.html
与所有子目录中的文件匹配:
/path/test/test.html
-已发送过期标头/path/test/noheader-test.html
- 没有发送 Expires 标头/path/test/child/test.html
-已发送过期标头/path/test/child/grandchild/test.html
-已发送过期标头
这就像路径中还有其他东西与正则表达式不匹配,因为当我将正则表达式更改为时,^/your/path/test/.+$
它匹配了。
想知道路径中缺失的部分是什么,我使用了正则表达式捕获组和指令Header
来让 Apache 告诉我缺失了什么,如下所示:
<DirectoryMatch ^/path/test/(?<MISSINGPART>.+)$>
<Files "test.html">
Header add X-TEST "expr=%{env:MATCH_MISSINGPART}"
</Files>
</DirectoryMatch>
这给出了以下标题:
/path/test/test.html
-x-test:"test.html"
/path/test/noheader-test.html
- 没有发送标题/path/test/child/test.html
-x-test:"child/test.html"
/path/test/child/grandchild/test.html
-x-test:"child/grandchild/test.html"
这说明DirectoryMatch
文件名也匹配?!
在 Apache 错误跟踪器上错误 41867有点符合这个描述所以可以解释这一点(我也测试了没有嵌套<Files>
指令并且标题值保持不变)
为了证明这一点,我尝试test.html
像这样替换正则表达式:
<DirectoryMatch "^/path/test/test.html$">
<Files "test.html">
Header add X-TEST "Match"
</Files>
</DirectoryMatch>
未X-TEST
返回任何标头。
但这确实意味着可以使正则表达式匹配我们感兴趣的匹配目录之后的任何非目录,如下所示:
<DirectoryMatch "^/path/test/[^/]+$">
<Files "test.html">
ExpiresActive on
ExpiresDefault A10
</Files>
</DirectoryMatch>
这将在所有需要的位置给出标题:
/path/test/test.html
-已发送过期标头/path/test/noheader-test.html
- 没有发送 Expires 标头/path/test/child/test.html
- 没有发送 Expires 标头/path/test/child/grandchild/test.html
- 没有发送 Expires 标头