通过ProxyPassMatch作为处理程序转发PHP请求,或者仅在文件存在时转发

我正在迁移我的服务器使用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文档不build议使用RewriteRule :“这是因为这个标志触发了使用默认的worker,它不处理连接池。

理想情况下,我想要在FileMatch块中使用ProxyPass(当前不支持),或者定义一个新的处理程序,通过fcgi代理并使用它来处理.php请求,类​​似于mod_php。

任何build议模拟标准的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> 

同上。

  • 我也无法弄清楚如何获得Apache VHOSTconfiguration路由不可查找的请求到404。
  • 同样,我也试图弄清楚如何通过ProxyPassMatch获得无扩展名的URL映射。
    • 当然…我可以通过php-fpm代理路由所有的东西 ,但是那样会导致javascript和css文件死掉。

理论解决scheme

我的猜测是,我不得不写一个自定义的404.php处理器 – 然后通过附加请求的文件作为查询string路由所有请求。

例如:

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

在理论上 – 并假定它们的上市顺序依然适用:

在达到ProxyPassMatch指令之前 ,任何404'd文件都将被捕获

我的解决scheme

  • php5-fpm(5.4.23)
  • Apache 2.4.2
  • Ubuntu 12.04 / 3.8.0-34 x86_64

为了处理php-fpm扩展URL,我改编了上面的代码,在我的VHOSTconfiguration文件中寻找无扩展名的URL:

 ... # 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] ... 

不漂亮,但它确实完成了工作:-(

只是作为一个class轮logging:

 AddHandler "proxy:unix:/path/to/socket.sock|fcgi://./" .php 

你需要一个最近的Apache 2.4(RedHat支持到2.4.6)

奥利弗

我也有同样的问题,而且花费的时间比我想象的要长得多。 由于这是我能find的唯一的post或文章,帮助我充分解决了这个问题,所以我想把我的解决schemejoin到这个组合中。

我的configuration:

  • Ubuntu 14.04
  • Apache 2.4.20
  • PHP-FPM 5.5.9-1ubuntu4.17(fpm-fcgi)(built:May 19 2016 19:08:26)

我遇到了一些额外的挑战:

  1. 我的ErrorDocument处理程序是一个PHP文件。
  2. 我的文档根目录的.htaccess文件中有一堆RedirectPermanent指令。 这些都没有被尊重,因为在redirect规则被评估之前,请求被代理到PHP-FPM。
  3. FilesMatch对我来说是不够的,因为我用类似于Wordpress的方式使用URL重写。 例如/mydir/mypath.html指向/mydir/script.php。 我无法让它匹配重写的url,虽然也许我忽略了一些问题?
  4. 我能够得到misterich的方法来工作,但是在阅读Apache的性能警告之后 ,我决定深入挖掘。

我的解决scheme基本是这样的

  1. 拦截并redirect不存在的目录和文件的请求,并将它们重写到error handling程序PHP文件。
  2. 使用另一个重写规则将重写的错误请求路由到PHP-FPM。
  3. 使用ProxyPassMatch将所有其他请求路由到PHP-FPM。

为了解决301redirect(#2),我将简单地利用error handling程序来发出redirect。

 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" 

当文件不存在时,我有同样的问题显示“文件未find”。 消息,这解决了我的问题,并允许我设置一个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>