У меня есть сайт, размещенный у провайдера виртуального хостинга. Это Apache с FPM / FastCGI и PHP 7.2
В качестве общего хостинга включен Конфигурация, к которой у меня есть доступ, - это htaccess, но, очевидно, не какой-либо из файлов конфигурации Apache.
У меня есть настраиваемая страница ошибок, настроенная в моем htaccess следующим образом: ErrorDocument 404 /error404.php
. Сегодня я заметил, что моя пользовательская страница с ошибкой 404 не отображается. Вместо обычного текста Файл не найден.
возвращается в браузер с кодом состояния 404 в заголовке. Дальнейшее расследование показало, что это происходит только тогда, когда запрашивается файл . Если вы запрашиваете несуществующий каталог , вы получаете настраиваемую страницу ошибки! Например, запрос mydomain.info/dummy.htm
дает ошибку, а запрос mydomain.info/dummy/
возвращает пользовательскую страницу ошибки.
Сервер регистрирует ошибку ] AH01071
, то есть Основной сценарий неизвестен
для каждого Файл не найден.
ошибка.
Похоже, что ModSecurity включен на сервере, потому что журналы регистрируют отклоненные злонамеренные запросы, например [клиент xxx.xxx.xxx.xxx] ModSecurity: Доступ запрещен с кодом 403 (фаза 2). ... etc
Кроме того, я недавно перешел на PHP 7.2 в соответствии с рекомендациями хостинг-провайдера. Однако возврат к версии 5.6 не меняет симптомов.
Есть идеи, что вызывает это? Я видел информацию, которая предполагает, что, возможно, ProxyPass
или ProxyErrorOverride
может решить проблему, но я не знаю, где это настроить.
Для записи, вот полный htaccess, бородавки и все такое:
RewriteEngine on
# AddType TYPE/SUBTYPE EXTENSION
AddType audio/mpeg mp3
AddType video/mp4 mp4 m4v
# Add WWW
RewriteCond %{HTTP_HOST} ^mydomain\.info [NC]
RewriteRule ^(.*) https://www.mydomain.info/$1 [R=301,L,NE]
# Redirect for .COM
RewriteCond %{HTTP_HOST} mydomain\.com$ [NC]
RewriteRule ^/?(.*) https://www.mydomain.info/$1 [R=301,L,NE]
# Force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# Home page canonicalization
RewriteCond %{THE_REQUEST} ^.*\/index\.htm\ HTTP/
RewriteRule ^(.*)index\.htm$ /$1 [R=301,L,NE]
# Removed page_missing.htm
Redirect 301 /page_missing.htm /new_page.htm#section_b
# Some content moved to sub-folder
Redirect 301 /extra_content.htm /extra/extra_content.htm
# Internally redirect all HTM & HTML URLs to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.(htm|html)$ /$1\.php
# Error 404 page
ErrorDocument 404 /error404.php
<IfModule mod_expires.c>
# Activate mod_expires for this directory
ExpiresActive on
# Default
ExpiresDefault "access plus 7 days"
# Default for actual documents
ExpiresByType text/html "access plus 15 minutes"
# cache CSS files for 7 days
ExpiresByType text/css "access plus 7 days"
# locally cache common resource types for 7 days
ExpiresByType image/jpg "access plus 7 days"
ExpiresByType image/jpeg "access plus 7 days"
ExpiresByType image/gif "access plus 7 days"
ExpiresByType image/png "access plus 7 days"
ExpiresByType application/pdf "access plus 7 days"
ExpiresByType audio/mpeg "access plus 7 days"
</IfModule>
# Внутреннее перенаправление всех URL-адресов HTM и HTML на PHP RewriteCond% {REQUEST_FILENAME}! -F RewriteRule ^ (. *) \. (Htm | html) $ /$1\.php
Я бы не ожидал, что это вызовет проблему, с которой вы столкнулись, однако у вас есть директивы, которые «вслепую» перезаписывают любой несуществующий .htm
(или .html
] ) к эквивалентному файлу .php
независимо от того, существует ли этот файл .php
или нет. (В этом случае документ об ошибке должен обнаруживать отсутствующий файл .php
, а не отсутствующий файл .htm
, который изначально был запрошен.)
Это также может объяснить разницу в вашем поведении наблюдают с запросом несуществующего «каталога» (т. е. запроса формы / dummy /
), который не может быть переписан вышеуказанной директивой и, кажется, «работает», как задумано (т. е. вызывается пользовательский документ об ошибке).
Вы можете изменить приведенное выше правило, чтобы перезаписать его в .php
, только если файл существует. Например:
# Internally redirect all HTM & HTML URLs to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*)\.(htm|html)$ /$1.php [L]
Нет необходимости экранировать буквальную точку в подстановке RewriteRule
. Вы должны включить флаг L
(хотя в настоящее время это последняя директива mod_rewrite, поэтому не имеет особого значения).
ОБНОВЛЕНИЕ: Если вы запрашиваете несуществующую страницу php, вы все равно получить ответ «Файл не найден»
Похоже на проблему конфигурации сервера. Вы можете "обойти" эту проблему, вручную переписав документ об ошибке:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ /error404.php [L]
Хотя вам, вероятно, потребуется изменить error404.php
, чтобы учесть это.
ИЛИ ... Я Также было бы любопытно, изменит ли запуск 404 из Apache (который, на первый взгляд, не имеет большого смысла) это поведение. Например, вместо приведенной выше перезаписи:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ - [R=404]
Идея этого подхода заключается в том, что он, как мы надеемся, вызовет внутренний подзапрос для документа об ошибке до того, как запрос будет передан обработчику PHP (который, похоже, что противоречит документу об ошибке). Затем обработчик PHP вызывается только для обслуживания документа об ошибке.