3

I have a virtual host on Apache 2.4.25 with PHP-FPM 7.1.4 connected via mod_proxy_fcgi as follows:

<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>

Most of the applications work flawlessly with this setup, but there is one application which uses PATH_INFO to to extract the request. The application has something like this in its .htaccess:

RewriteEngine On

RewriteCond $1 ^index\.php
RewriteRule ^(.*)$ - [PT,L]

RewriteRule ^(.*)$ index.php/$1 [PT,L]

Simply put, everything what's not index.php should be passed to it as a path. Visiting URL http://example.com/index.php/test works and shows [PATH_INFO] => /test as expected, but visiting http://example.com/test dies with

AH01071: Got error 'Primary script unknown\n'

Setting LogLevel trace6 for both mod_rewrite and mod_proxy_fcgi shows that the redirection is done properly and the proper paths are also passed to PHP-FPM.

Traces for /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

Traces for /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

How to get the Apache to properly rewrite the URLs and pass the PATH_INFO at the same time?

Note: This question might seem to be similar as Apache 2.4 + PHP-FPM + ProxyPassMatch but in my case I'm already using SetHandler. The problem is with the PATH_INFO part, which the answers there don't seem to solve.

1

1 Answer 1

5

After few days of struggle, I have captured and examined CGI headers sent between Apache and PHP-FPM and tested the same also with different versions of said components. It turns out that different versions of Apache set SCRIPT_FILENAME variable differently which is unaccounted for in PHP-FPM.
Apache 2.4.18 (default in Ubuntu 16.04 which I use) populates the variable as follows:

SCRIPT_FILENAME proxy:fcgi://localhost/srv/www/index.php

Whereas Apache 2.4.25 sets:

SCRIPT_FILENAME /srv/www/index.php

Apache documentation of mod_proxy_fcgi mentions a directive ProxyFCGIBackendType available since Apache 2.4.26 (not released yet as of 2017-05-02), which defaults to "FPM". There is a following note in the description:

One example of values that change based on the setting of this directive is SCRIPT_FILENAME. When using mod_proxy_fcgi historically, SCRIPT_FILENAME was prefixed with the string "proxy:fcgi://". This variable is what some generic FastCGI applications would read as their script input, but PHP-FPM would strip the prefix then remember it was talking to Apache. In 2.4.21 through 2.4.25, this prefix was automatically stripped by the server, breaking the ability of PHP-FPM to detect and interoperate with Apache in some scenarios.

Seems I have coincidentally found "some scenario". Answer to my own question is then: Do not use Apache 2.4.21 through 2.4.25 as they contain a bug. Use either lower version or wait for newer where the bug is fixed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .