Пересылка PHP-запросов через ProxyPassMatch в качестве обработчика или только при наличии файла
Я перевожу свой сервер, чтобы использовать mod_proxy_fcgi и php-fpm вместо mod_php. Apache может пересылать запросы.php прокси-серверу fcgi, а PHP выполняется правильно. У меня это работает с:
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/$1
К сожалению, Apache перенаправляет все запросы.php на прокси, даже если файл не существует. Это вызывает несколько проблем. Мое правило ErrorDocument не вызывается, и DirectoryIndex index.php index.html
не возвращается к index.html.
Мне удалось исправить эти проблемы с mod_rewrite:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} ^/((.*\.php)(/.*)?)$
RewriteCond /var/www/html/%2 -f
RewriteRule . fcgi://127.0.0.1:9000/var/www/html/%1 [P]
Однако документация Apache не рекомендует RewriteRule: "Это связано с тем, что этот флаг вызывает использование работника по умолчанию, который не обрабатывает пулы соединений".
В идеале, я думаю, что я либо хотел бы использовать ProxyPass в блоке FilesMatch (в настоящее время не поддерживается), либо определить новый обработчик, который проксирует через fcgi и использует его для обработки запросов.php, аналогично тому, что делает mod_php.
Любые предложения для моделирования стандартной установки mod_php, но на самом деле прокси через fcgi?
5 ответов
Один из вариантов - установить mod_proxy_handler: https://gist.github.com/progandy/6ed4eeea60f6277c3e39
Или вы можете подождать Apache 2.4.10, который должен включать модуль.
В основном модуль позволяет вам сделать это:
#tcp
<FilesMatch \.php$>
SetHandler proxy:fcgi://localhost:9000
</FilesMatch>
#uds
<FilesMatch \.php$>
SetHandler "proxy:unix:/path/to/socket.sock|fcgi://./"
</FilesMatch>
Просто для записи в один лайнер:
AddHandler "proxy:unix:/path/to/socket.sock|fcgi://./" .php
Вам понадобится недавний Apache 2.4 (RedHat вернул его на 2.4.6)
Оливер
У меня была та же проблема, когда файл не существовал, показывал "Файл не найден". сообщение, это решило мою проблему и позволило мне настроить страницу 404:
<VirtualHost *:80>
---------- content --------
DocumentRoot /home/user/public_html/domain.tld
#this disables php execution if you wish to show only html files
#ProxyPass /errors !
ProxyErrorOverride On
# /errors folder is located in public_html
ErrorDocument 404 /errors/404.php
</VirtualHost>
У меня была точно такая же проблема, как у ide, и я потратил гораздо больше времени, пытаясь решить эту проблему, чем я надеялся. Поскольку это единственная публикация или статья, которую мне удалось найти, которая помогла мне адекватно решить проблему, я хотел добавить свое решение в набор.
Моя конфигурация:
- Ubuntu 14.04
- Apache 2.4.20
- PHP-FPM 5.5.9-1ubuntu4.17 (fpm-fcgi) (построено: 19 мая 2016 г. 19:08:26)
Я столкнулся с несколькими дополнительными проблемами:
- Мой обработчик ErrorDocument - это файл PHP.
- У меня есть куча директив RedirectPermanent в корне моего файла.htaccess. Это не было выполнено, потому что запросы были переданы в PHP-FPM до оценки правил перенаправления.
- FilesMatch было недостаточно для меня, потому что я использую переписывание URL аналогично Wordpress. Например, /mydir/mypath.html указывает на /mydir/script.php. Я не мог заставить его соответствовать переписанным URL, хотя, возможно, я что-то упустил?
- Мне удалось понять подход мистериха к работе, но после прочтения предупреждения о производительности Apache я решил продолжить.
Мое решение в основном это:
- Перехватывать и перенаправлять запросы на несуществующие каталоги и файлы и переписывать их в PHP-файл обработчика ошибок.
- Используйте другое правило перезаписи, чтобы направить мой переписанный запрос об ошибке в PHP-FPM.
- Направьте все остальные запросы в PHP-FPM, используя ProxyPassMatch.
Чтобы решить проблему перенаправления 301 (#2), я просто использую обработчик ошибок для выдачи перенаправлений.
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^.*\.php$ /error.php?error=404&requestUri=$1
RewriteCond %{REQUEST_FILENAME} ^/(error.php)$
RewriteCond %{DOCUMENT_ROOT}/%1 -f
RewriteRule . fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/%1 [P]
# PHP-FPM
ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000/var/www/mysite.com"
То же самое и в ОП.
- Я также не мог понять, как получить конфигурацию Apache VHOST для маршрутизации необнаруживаемых запросов на 404.
- Точно так же я был в тупике, пытаясь выяснить, как получить URL без расширения для сопоставления через
ProxyPassMatch
,- Конечно... Я мог бы все через
php-fpm
прокси, но это убило javascript и css файлы.
- Конечно... Я мог бы все через
Теоретическое решение
Я предполагаю, что я должен написать 404.php
обработчик - и затем направляет все запросы через него, добавляя запрошенные файлы в строку запроса.
Например:
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-s
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-l
RewriteRule ^.*$ fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/404.php?no_comprende=%{REQUEST_URI} [P]
...
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/$1
...
в теории - и при условии, что порядок, в котором они перечислены, все еще применяется как обычно:
Любой файл 404 будет перехвачен до
ProxyPassMatch
директива была достигнута
МОЕ РЕШЕНИЕ
- php5-fpm (5.4.23)
- Apache 2.4.2
- Ubuntu 12.04 / 3.8.0-34 x86_64
Для обработки URL-адресов без расширения php-fpm
Я адаптировал вышеупомянутое, чтобы искать URL без расширений как таковые в моей конфигурации VHOST:
...
# Extensionless URL's
RewriteCond %{REQUEST_FILENAME} ^/((.*)(/.*)?)$
RewriteCond %{DOCUMENT_ROOT}/%2.php -f
RewriteRule !.*\.php$ fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/%1.php [P]
# files w/ .php extensions
RewriteCond %{REQUEST_FILENAME} ^/((.*\.php)(/.*)?)$
RewriteCond %{DOCUMENT_ROOT}/%2 -f
RewriteRule . fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/%1 [P]
...
Не красиво, но это делает работу:-(
У меня была та же проблема, что при отсутствии index.php apache не возвращается к index.html при использовании ProxyPassMatch.
Вместо этого я использовал (apache 2.4):
<FilesMatch "\.php$">
SetHandler "proxy:unix:/usr/local/php73/var/run/mpelov-php-fpm.sock|fcgi://localhost/"
</FilesMatch>
Я не уверен, что это сработает на apache 2.2.
Проблема в том, что вы не можете указать путь к файлу. Таким образом, http://example.com/file.php будет сопоставлен с /file.php, что обычно нормально, но если php-fpm использует chroot, это немного сложнее, потому что для php это файл /file.php, и если вы иметь http://example.com/file.html, тогда apache обрабатывает запрос, а путь - //file.html
Таким образом, вы не можете использовать filematch с fpm+chroot.