Apache: Служите содержанию из файлов, которые ограничиваются

В моей установке 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 запрещать доступ к каталогу, все еще позволяя себе служить тем файлам когда необходимый?

1
задан 7 August 2014 в 16:39
1 ответ

OK Я придумал, как это сделать.

Я использовал 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 не делает явного перенаправления, а только внутреннего.

.
0
ответ дан 4 December 2019 в 08:33

Теги

Похожие вопросы