在使用 mod_proxy_fcgi 和 PATH_INFO 時重寫 URL 會出現錯誤 404
我在 Apache 2.4.25 上有一個虛擬主機,通過 mod_proxy_fcgi 連接 PHP-FPM 7.1.4,如下所示:
<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/testAH01071: Got error 'Primary script unknown\n'
mod_rewrite 和 mod_proxy_fcgi 的設置
LogLevel trace6
表明重定向正確完成,並且正確的路徑也傳遞給 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 部分,那裡的答案似乎沒有解決。
經過幾天的努力,我已經擷取並檢查了在 Apache 和 PHP-FPM 之間發送的 CGI 標頭,並使用所述組件的不同版本進行了測試。事實證明,不同版本的 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
mod_proxy_fcgi 的 Apache 文件提到了自 Apache 2.4.26(截至 2017-05-02 尚未發布)以來可用的指令ProxyFCGIBackendType ,預設為“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,因為它們包含錯誤。使用較低版本或等待修復錯誤的更新版本。