В моей настройке Apache у меня есть каталог со страницами с моими ошибками (404 403). Однако я не хочу, чтобы этот каталог был доступен для просмотра напрямую - я хотел бы получить к нему доступ, чтобы вернуть 404. Итак, я сделал следующее:
# Use /hidden/404/ as the 404 page
ErrorDocument 404 /hidden/404/
# Use /hidden/403/ as the 403 page
ErrorDocument 403 /hidden/403/
<Directory /path/to/root/hidden/>
# All requests return 404
RedirectMatch 404 .*
</Directory>
проблема в том, что Apache, похоже, не желает обслуживать файлы в все в этом случае, даже когда я говорю это явно (то есть для обработки ошибок 404 и 403). На самом деле, когда я навещаю /hidden
, Я получаю следующее сообщение:
The requested URL /hidden/404/ was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an
ErrorDocument to handle the request.
В любом случае я могу сказать Apache, чтобы он запретил доступ к каталогу, но при этом позволял себе обслуживать эти файлы при необходимости?
Хорошо, я нашел способ сделать это.
Я использовал mod_rewrite
, который представляет собой модуль Apache (по умолчанию поставляется со всеми установками) для перезаписи запрошенных URL-адресов на лету. Вот код:
# Custom error pages
ErrorDocument 404 /hidden/404/index.html
ErrorDocument 403 /hidden/403/index.html
# Pretend that /hidden doesn't exist
# (unless this is an internal redirect,
# such as rendering a 404 or 403)
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^/hidden/.* - [L,R=404]
Итак, давайте пройдемся по этим строкам. В ErrorDocument
директивы не изменились - они просто говорят, какую страницу следует обслуживать при возникновении данной ошибки.
Настоящее мясо в RewriteCond
и RewriteRule
директивы. Что за RewriteRule
директива говорит следующее: если запрашивается URL-адрес, путь которого соответствует регулярному выражению ^/hidden/.*
(по сути, любой путь к чему-либо в / hidden / или его поддереве), оставьте URL-адрес без изменений (это то, что -
означает), но больше не интерпретируйте RewriteRule
директивы (вот что L
означает), и вернуть код ошибки 404 (это то, что R=404
средства).
Это в сочетании с ErrorDocument 404 /hidden/404/index.html
директива, может показаться, помогает. Проблема, однако, в том, что когда Apache переходит на обслуживание /hidden/404/index.html
, он снова проходит через эти правила. Это означает, что RewriteRule
выполняется директива, которая, в свою очередь, требует отрисовки 404, и все это просто бесконечные циклы.
Таким образом, мы используем RewriteCond
директива, чтобы этого не произошло. RewriteCond
директивы являются условными - RewriteRule
указанная ниже директива будет выполнена только в том случае, если выполнено условие. В этом случае условием является "переменная среды REDIRECT_STATUS
равно пустой строке. "Теперь REDIRECT_STATUS
это переменная среды, которая устанавливается ErrorDocument
, и содержит код состояния, который перенаправляется (так, если ErrorDocument 404 ...
директива была запущена, ей будет присвоено значение "404"). Однако если нет ErrorDocument
директива была выполнена, то REDIRECT_STATUS
не было бы установлено, поэтому запрос его значения просто вернет пустую строку. Таким образом, RewriteCond %{ENV:REDIRECT_STATUS} =""
по сути говорит: "не беспокойтесь об оценке RewriteRule
приведенной ниже директиве, если только мы не обрабатываем страницу с ошибкой ".
нота: если вы посмотрели на RewriteRule
документации, вы могли заметить, что R
Аргумент должен выполнять явное перенаправление. Причина, по которой он отлично работает в этом случае, заключается в том, что есть недокументированная функция R
аргумент, который заключается в том, что он перенаправляет только коды класса 300. Таким образом, R=404
не делает явного перенаправления, только внутреннее.