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

Перенаправление запросов 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?

Один из вариантов - установить 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)

Я столкнулся с несколькими дополнительными проблемами:

  1. Мой обработчик ErrorDocument - это файл PHP.
  2. У меня есть куча директив RedirectPermanent в корневом файле .htaccess моего документа. Они не соблюдались, потому что запросы передавались в PHP-FPM до оценки правил перенаправления.
  3. FilesMatch для меня было недостаточно, потому что я использую перезапись URL аналогично Wordpress. Например. /mydir/mypath.html указывает на /mydir/script.php. Я не мог заставить его соответствовать переписанным URL-адресам, хотя, возможно, я что-то пропустил?
  4. Я смог заставить работать мистерихский подход, но после прочтения Apache предупреждение о производительности, Решил покопаться дальше.

Мое решение в основном таково:

  1. Перехватывать и перенаправлять запросы на несуществующие каталоги и файлы и перезаписывать их в файл PHP обработчика ошибок.
  2. Используйте другое правило перезаписи, чтобы направить мой перезаписанный запрос об ошибке в PHP-FPM.
  3. Направляйте все остальные запросы в 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"

То же к OP.

  • Я также не мог понять, как получить конфигурацию 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.