У меня проблема, которая кажется простой. Я хочу применить группу директив конфигурации к одному файлу (в данном случае 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
по академическим причинам. (Изменить: также, чтобы процитировать документацию, Важно никогда не использовать при попытке ограничить доступ к объектам в файловой системе.)
Единственный способ, которым я нашел эту работу, - это использовать следующее:
<DirectoryMatch ^/home/amoe/opt/httpd/htdocs/[^/]+$>
<Files "test.html">
ExpiresActive on
ExpiresDefault A10
</Files>
</DirectoryMatch>
Я считаю, что лишний [^/]+
не требуется, чтобы это работало, см. ниже полное объяснение того, как я пришел к такому выводу, и поэтому я считаю, что это ошибка в Apache.
Все перечисленное основано на среде Ubuntu 16.04.1 LTS под управлением Apache 2.4.23 с тестовыми файлами в следующих местах:
/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 не отправлен