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

Apache - пользовательская страница ошибок, возвращающая ошибку AH01071 только для файловых запросов

У меня есть сайт, размещенный у провайдера виртуального хостинга. Это Apache с FPM / FastCGI и PHP 7.2.

Поскольку у меня есть общий хостинг, единственная конфигурация, к которой у меня есть доступ, - это htaccess, но, очевидно, не какой-либо из файлов конфигурации Apache.

У меня есть настраиваемая страница ошибок, настроенная в моем htaccess, например: ErrorDocument 404 /error404.php. Сегодня я заметил, что моя пользовательская страница с ошибкой 404 не отображается. Вместо обычного текста File not found. возвращается в браузер с кодом состояния 404 в заголовке. Дальнейшее расследование показало, что это происходит только в том случае, если запрашивается файл. Если вы запрашиваете несуществующий каталог тогда вы получите настраиваемую страницу ошибки! Например, запрос mydomain.info/dummy.htm выдает ошибку, но запрашивает mydomain.info/dummy/ возвращает настраиваемую страницу ошибки.

Сервер регистрирует ошибку AH01071 который Primary script unknown для каждого File not found. ошибка.

Похоже, что ModSecurity включен на сервере, потому что журналы регистрируют отклоненные вредоносные запросы, например [client xxx.xxx.xxx.xxx] ModSecurity: Access denied with code 403 (phase 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> 
# Internally redirect all HTM & HTML URLs to 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 flag (хотя в настоящее время это последняя директива 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 вызывается только для обслуживания документа об ошибке.