Назад | Перейти на главную страницу

Примените конфигурацию Apache httpd к конкретному файлу, а не к подкаталогам

У меня проблема, которая кажется простой. Я хочу применить группу директив конфигурации к одному файлу (в данном случае 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 не отправлен