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> 

1 ответ

Решение
# 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 флаг (хотя в настоящее время это последняя директива 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 вызывается только для обработки документа об ошибке.

Другие вопросы по тегам