У меня есть виртуальный хост на Apache 2.4.25 с PHP-FPM 7.1.4, подключенный через mod_proxy_fcgi следующим образом:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /srv/www/example.com
<Directory /srv/www/example.com>
AllowOverride All
Require all granted
</Directory>
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
<FilesMatch ".+\.ph(p[3457]?|t|tml)$">
SetHandler "proxy:unix:/run/php/example.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
Большинство приложений работают безупречно с этой настройкой, но есть одно приложение, которое использует PATH_INFO для извлечения запроса. В файле .htaccess приложения есть что-то вроде этого:
RewriteEngine On
RewriteCond $1 ^index\.php
RewriteRule ^(.*)$ - [PT,L]
RewriteRule ^(.*)$ index.php/$1 [PT,L]
Проще говоря, все, чего нет index.php
следует передать ему как путь. URL посещения http://example.com/index.php/test работает и показывает [PATH_INFO] => /test
как и ожидалось, но в гостях http://example.com/test умирает с
AH01071: Got error 'Primary script unknown\n'
Настройка LogLevel trace6
для mod_rewrite и mod_proxy_fcgi показывает, что перенаправление выполнено правильно и правильные пути также передаются в PHP-FPM.
Следы для /index.php/test:
[Sat Apr 29 09:40:41.156316 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141400a0/initial] [perdir /srv/www/example.com/] add path info postfix: /srv/www/example.com/index.php -> /srv/www/example.com/index.php/test
[Sat Apr 29 09:40:41.156334 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141400a0/initial] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/index.php/test -> index.php/test
[Sat Apr 29 09:40:41.156348 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141400a0/initial] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'index.php/test'
[Sat Apr 29 09:40:41.156352 2017] [rewrite:trace4] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141400a0/initial] [perdir /srv/www/example.com/] RewriteCond: input='index.php/test' pattern='^index\\.php' => matched
[Sat Apr 29 09:40:41.156355 2017] [rewrite:trace2] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141400a0/initial] [perdir /srv/www/example.com/] forcing '/srv/www/example.com/index.php' to get passed through to next API URI-to-filename handler
[Sat Apr 29 09:40:41.156358 2017] [rewrite:trace1] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141400a0/initial] [perdir /srv/www/example.com/] initial URL equal rewritten URL: /srv/www/example.com/index.php [IGNORING REWRITE]
[Sat Apr 29 09:40:41.156368 2017] [proxy_fcgi:debug] [pid 3014:tid 140574363391744] mod_proxy_fcgi.c(913): [client xx.xx.xx.xx:32622] AH01076: url: fcgi://localhost/srv/www/example.com/index.php proxyname: (null) proxyport: 0
[Sat Apr 29 09:40:41.156371 2017] [proxy_fcgi:debug] [pid 3014:tid 140574363391744] mod_proxy_fcgi.c(920): [client xx.xx.xx.xx:32622] AH01078: serving URL fcgi://localhost/srv/www/example.com/index.php
[Sat Apr 29 09:40:41.156510 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/test -> test
[Sat Apr 29 09:40:41.156519 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'test'
[Sat Apr 29 09:40:41.156535 2017] [rewrite:trace4] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] RewriteCond: input='test' pattern='^index\\.php' => not-matched
[Sat Apr 29 09:40:41.156538 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/test -> test
[Sat Apr 29 09:40:41.156541 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'test'
[Sat Apr 29 09:40:41.156563 2017] [rewrite:trace2] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] rewrite 'test' -> 'index.php/test'
[Sat Apr 29 09:40:41.156567 2017] [rewrite:trace3] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] add per-dir prefix: index.php/test -> /srv/www/example.com/index.php/test
[Sat Apr 29 09:40:41.156571 2017] [rewrite:trace2] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] forcing '/srv/www/example.com/index.php/test' to get passed through to next API URI-to-filename handler
[Sat Apr 29 09:40:41.156575 2017] [rewrite:trace2] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] strip document_root prefix: /srv/www/example.com/index.php/test -> /index.php/test
[Sat Apr 29 09:40:41.156579 2017] [rewrite:trace1] [pid 3014:tid 140574363391744] mod_rewrite.c(477): [client xx.xx.xx.xx:32622] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda1413e0a0/subreq] [perdir /srv/www/example.com/] internal redirect with /index.php/test [INTERNAL REDIRECT]
[Sat Apr 29 09:40:41.158640 2017] [proxy_fcgi:trace4] [pid 3014:tid 140574363391744] util_script.c(571): [client xx.xx.xx.xx:32622] Headers from script 'index.php':
[Sat Apr 29 09:40:41.158661 2017] [proxy_fcgi:trace4] [pid 3014:tid 140574363391744] util_script.c(572): [client xx.xx.xx.xx:32622] Content-type: text/html; charset=UTF-8
Следы для / test:
[Sat Apr 29 09:45:01.600510 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/test -> test
[Sat Apr 29 09:45:01.600527 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'test'
[Sat Apr 29 09:45:01.600533 2017] [rewrite:trace4] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] RewriteCond: input='test' pattern='^index\\.php' => not-matched
[Sat Apr 29 09:45:01.600535 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/test -> test
[Sat Apr 29 09:45:01.600537 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'test'
[Sat Apr 29 09:45:01.600540 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] rewrite 'test' -> 'index.php/test'
[Sat Apr 29 09:45:01.600550 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] add per-dir prefix: index.php/test -> /srv/www/example.com/index.php/test
[Sat Apr 29 09:45:01.600553 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] forcing '/srv/www/example.com/index.php/test' to get passed through to next API URI-to-filename handler
[Sat Apr 29 09:45:01.600556 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] strip document_root prefix: /srv/www/example.com/index.php/test -> /index.php/test
[Sat Apr 29 09:45:01.600560 2017] [rewrite:trace1] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141b40a0/initial] [perdir /srv/www/example.com/] internal redirect with /index.php/test [INTERNAL REDIRECT]
[Sat Apr 29 09:45:01.600621 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a1a78/initial/redir#1] [perdir /srv/www/example.com/] add path info postfix: /srv/www/example.com/index.php -> /srv/www/example.com/index.php/test
[Sat Apr 29 09:45:01.600626 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a1a78/initial/redir#1] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/index.php/test -> index.php/test
[Sat Apr 29 09:45:01.600628 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a1a78/initial/redir#1] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'index.php/test'
[Sat Apr 29 09:45:01.600643 2017] [rewrite:trace4] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a1a78/initial/redir#1] [perdir /srv/www/example.com/] RewriteCond: input='index.php/test' pattern='^index\\.php' => matched
[Sat Apr 29 09:45:01.600646 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a1a78/initial/redir#1] [perdir /srv/www/example.com/] forcing '/srv/www/example.com/index.php' to get passed through to next API URI-to-filename handler
[Sat Apr 29 09:45:01.600648 2017] [rewrite:trace1] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a1a78/initial/redir#1] [perdir /srv/www/example.com/] initial URL equal rewritten URL: /srv/www/example.com/index.php [IGNORING REWRITE]
[Sat Apr 29 09:45:01.600664 2017] [proxy_fcgi:debug] [pid 3013:tid 140574514460416] mod_proxy_fcgi.c(913): [client xx.xx.xx.xx:32639] AH01076: url: fcgi://localhost/srv/www/example.com/index.php proxyname: (null) proxyport: 0
[Sat Apr 29 09:45:01.600666 2017] [proxy_fcgi:debug] [pid 3013:tid 140574514460416] mod_proxy_fcgi.c(920): [client xx.xx.xx.xx:32639] AH01078: serving URL fcgi://localhost/srv/www/example.com/index.php
[Sat Apr 29 09:45:01.600790 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/test -> test
[Sat Apr 29 09:45:01.600795 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'test'
[Sat Apr 29 09:45:01.600799 2017] [rewrite:trace4] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] RewriteCond: input='test' pattern='^index\\.php' => not-matched
[Sat Apr 29 09:45:01.600801 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] strip per-dir prefix: /srv/www/example.com/test -> test
[Sat Apr 29 09:45:01.600803 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] applying pattern '^(.*)$' to uri 'test'
[Sat Apr 29 09:45:01.600805 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] rewrite 'test' -> 'index.php/test'
[Sat Apr 29 09:45:01.600807 2017] [rewrite:trace3] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] add per-dir prefix: index.php/test -> /srv/www/example.com/index.php/test
[Sat Apr 29 09:45:01.600810 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] forcing '/srv/www/example.com/index.php/test' to get passed through to next API URI-to-filename handler
[Sat Apr 29 09:45:01.600813 2017] [rewrite:trace2] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] strip document_root prefix: /srv/www/example.com/index.php/test -> /index.php/test
[Sat Apr 29 09:45:01.600815 2017] [rewrite:trace1] [pid 3013:tid 140574514460416] mod_rewrite.c(477): [client xx.xx.xx.xx:32639] xx.xx.xx.xx - - [example.com/sid#7fda1635d360][rid#7fda141a30a0/subreq] [perdir /srv/www/example.com/] internal redirect with /index.php/test [INTERNAL REDIRECT]
[Sat Apr 29 09:45:01.602797 2017] [proxy_fcgi:error] [pid 3013:tid 140574514460416] [client xx.xx.xx.xx:32639] AH01071: Got error 'Primary script unknown\n'
[Sat Apr 29 09:45:01.602833 2017] [proxy_fcgi:trace4] [pid 3013:tid 140574514460416] util_script.c(571): [client xx.xx.xx.xx:32639] Headers from script 'index.php':
[Sat Apr 29 09:45:01.602839 2017] [proxy_fcgi:trace4] [pid 3013:tid 140574514460416] util_script.c(572): [client xx.xx.xx.xx:32639] Status: 404 Not Found
[Sat Apr 29 09:45:01.602842 2017] [proxy_fcgi:trace4] [pid 3013:tid 140574514460416] util_script.c(572): [client xx.xx.xx.xx:32639] Content-type: text/html; charset=UTF-8
Как заставить Apache правильно переписывать URL-адреса и одновременно передавать PATH_INFO?
Примечание: Этот вопрос может показаться похожим на Apache 2.4 + PHP-FPM + ProxyPassMatch но в моем случае я уже использую SetHandler
. Проблема связана с частью PATH_INFO, ответы на которую, похоже, не решают.
После нескольких дней борьбы я захватил и изучил заголовки CGI, отправляемые между Apache и PHP-FPM, и протестировал то же самое с разными версиями указанных компонентов. Оказывается, разные версии Apache устанавливают SCRIPT_FILENAME
по-разному, что не учитывается в PHP-FPM.
Apache 2.4.18 (по умолчанию в Ubuntu 16.04, который я использую) заполняет переменную следующим образом:
SCRIPT_FILENAME proxy:fcgi://localhost/srv/www/index.php
В то время как Apache 2.4.25 устанавливает:
SCRIPT_FILENAME /srv/www/index.php
В документации Apache для mod_proxy_fcgi упоминается директива ProxyFCGIBackendType доступен начиная с Apache 2.4.26 (еще не выпущен по состоянию на 02.05.2017), по умолчанию используется "FPM". В описании есть следующее примечание:
Одним из примеров значений, которые меняются в зависимости от настройки этой директивы, является SCRIPT_FILENAME. Исторически при использовании mod_proxy_fcgi перед SCRIPT_FILENAME ставилась строка «proxy: fcgi: //». Эта переменная - это то, что некоторые общие приложения FastCGI будут читать как входные данные сценария, но PHP-FPM удалял префикс, а затем запоминал, что он разговаривал с Apache. В версиях с 2.4.21 по 2.4.25 этот префикс был автоматически удален сервером, что нарушало способность PHP-FPM обнаруживать Apache и взаимодействовать с ним в некоторых сценариях.
Кажется, случайно нашел «какой-то сценарий». Тогда ответ на мой собственный вопрос: Не используйте Apache с 2.4.21 по 2.4.25, поскольку они содержат ошибку. Используйте либо более раннюю версию, либо дождитесь более новой, где ошибка будет исправлена.