Apache 2.4 + PHP-FPM + ProxyPassMatch

apf*_*box 35 php-fpm apache-2.4

我最近在本地机器上安装了 Apache 2.4,以及使用 PHP-FPM 的 PHP 5.4.8。

一切都很顺利(过了一会儿......)但仍然有一个奇怪的错误:

我像这样为 PHP-FPM 配置了 Apache:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

它有效,例如,如果我打电话给http://localhost/info.php我得到正确的phpinfo()(它只是一个测试文件)。

但是,如果我调用目录,则会File not found.在错误日志中收到带有正文的 404 :

[Tue Nov 20 21:27:25.191625 2012] [proxy_fcgi:error] [pid 28997] [client ::1:57204] AH01071: Got error 'Primary script unknown\n'
Run Code Online (Sandbox Code Playgroud)

更新

我现在尝试使用 mod_rewrite 进行代理:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"

    RewriteEngine on    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P]
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

但问题是:它总是重定向,因为http://localhost/自动http://localhost/index.php请求,因为

DirectoryIndex index.php index.html
Run Code Online (Sandbox Code Playgroud)

更新 2

好的,所以我想“也许首先检查是否有文件要提供给代理:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"

    RewriteEngine on    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P]
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

现在完全重写不再起作用了......

更新 3

现在我有了这个解决方案:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"

    RewriteEngine on    
    RewriteCond /Users/apfelbox/WebServer/%{REQUEST_FILENAME} -f
    RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P]
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

首先检查是否有一个文件要传递给 PHP-FPM(带有完整路径和绝对路径),然后进行重写。

当在子目录中使用 URL 重写时,这不起作用,对于像http://localhost/index.php/test/ So back to square one 这样的URL 也会失败。


有任何想法吗?

Fra*_*coA 39

经过数小时的搜索和阅读 Apache 文档,我想出了一个允许使用池的解决方案,并且即使 url 包含 .php 文件,也允许 .htaccess 中的 Rewrite 指令工作。

<VirtualHost ...>

 ...

 # This is to forward all PHP to php-fpm.
 <FilesMatch \.php$>
   SetHandler "proxy:unix:/path/to/socket.sock|fcgi://unique-domain-name-string/"
 </FilesMatch>

 # Set some proxy properties (the string "unique-domain-name-string" should match
 # the one set in the FilesMatch directive.
 <Proxy fcgi://unique-domain-name-string>
   ProxySet connectiontimeout=5 timeout=240
 </Proxy>

 # If the php file doesn't exist, disable the proxy handler.
 # This will allow .htaccess rewrite rules to work and 
 # the client will see the default 404 page of Apache
 RewriteCond %{REQUEST_FILENAME} \.php$
 RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
 RewriteRule (.*) - [H=text/html]

</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

根据 Apache 文档,SetHandler 代理参数需要 Apache HTTP Server 2.4.10。

我希望这个解决方案也能帮助你。

  • 这绝对是 2015 年的答案,这里的其他一切都是现代设置的废话(假设 debian stable) (2认同)
  • 目前使用这个 RewriteRule 似乎很危险,因为如果它们在 Aliased 目录中并且因此不存在于 %{DOCUMENT_ROOT}/%{REQUEST_URI} 中,它可能会以简单的方式暴露 `config.php` 文件。 (2认同)
  • 惊人的 9 行代码。这是圣杯,也是唯一对我 100% 有效的东西。旁注:如果您要从使用 LocationMatch 的解决方案切换,则无需将绝对文件路径附加到 fcgi url。打开代理并重写 apache 中的日志记录以注意这一点。 (2认同)
  • +1,因为这篇文章与我见过的所有其他资源不同,帮助我理解了“唯一域名字符串”应该代表什么。 (2认同)

Ale*_*lex 11

我昨天也遇到了这个问题——Apache 2.4 从Debian/experimental移到Debian/unstable迫使我处理这些新东西;当然不是在我们的生产服务器上;)。

在阅读了数百万个站点、Apache 文档、错误报告和错误日志中的调试输出后,我终于让它工作了。不,目前还不支持带有 sockets 的 FPM。默认的 Debian 配置已经使用套接字一段时间了,所以 Debian 用户也必须改变它。

这是适用于 CakePHP 站点和 PHPMyAdmin 的方法(如果您使用的是 Debian 软件包,后者需要一些配置),所以我可以确认它mod_rewrite仍然可以按预期进行花哨的 URL 重写。

请注意DirectoryIndex index.php,这可能是您的配置都不适用于“文件夹”的原因(至少这在这里不起作用)。

我仍然获取File not found.目录,但前提是没有索引文件可以解析。也很想摆脱它,但它不像现在那么重要。


<VirtualHost *:80>
    ServerName site.localhost

    DocumentRoot /your/site/webroot
    <Directory />
            Options FollowSymlinks
            DirectoryIndex index.php
            AllowOverride All
            Require all granted
    </Directory>

    <LocationMatch "^(.*\.php)$">
            ProxyPass fcgi://127.0.0.1:9000/your/site/webroot
    </LocationMatch>

    LogLevel debug
    ErrorLog /your/site/logs/error.log
    CustomLog /your/site/logs/access.log combined
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

上面的 vhost 与根目录中的 .htaccess 完美配合,如下所示:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)

我不太明白你的意思URL rewriting inside a subdirectory(我只是重写根的 index.php)。


(哦,你必须确保 Xdebug 不会与你系统上的 FPM 冲突,开箱即用,他们想要使用相同的端口。)