아파치 2.4 + PHP-FPM + ProxyPassMatch http://localhost/자동 http://localhost/index.php으로 요청 되기 때문에

최근에 PHP-FPM을 사용하여 PHP 5.4.8과 함께 로컬 컴퓨터에 Apache 2.4를 설치했습니다.

모든 것이 순조롭게 진행되었지만 (잠깐 후 …) 여전히 이상한 오류가 있습니다.

다음과 같이 PHP-FPM 용 Apache를 구성했습니다.

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

예를 들어 전화 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'

최신 정보

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

그러나 문제는 : http://localhost/자동 http://localhost/index.php으로 요청 되기 때문에 항상 리디렉션됩니다.

DirectoryIndex index.php index.html

업데이트 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>

이제 완전한 재 작성이 더 이상 작동하지 않습니다 …

업데이트 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>

먼저, 전체 경로 와 절대 경로를 사용하여 PHP-FPM에 전달할 파일이 있는지 확인한 다음 다시 작성하십시오.

하위 디렉토리 내에서 URL 다시 쓰기를 사용할 때는 작동하지 않으며 http://localhost/index.php/test/
So 와 같은 URL은 정사각형으로 돌아갑니다.


어떤 아이디어?



답변

몇 시간 동안 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>

Apache 문서에 따라 SetHandler 프록시 매개 변수에는 Apache HTTP Server 2.4.10이 필요합니다.

이 솔루션이 도움이되기를 바랍니다.


답변

어제 나도이 문제에 부딪쳤다 – Apache 2.4는 Debian / experimental 에서 Debian / unstable로 옮겨서이 새로운 것들을 다루도록 강요했다. 물론 프로덕션 서버에는 없습니다.).

오류 로그에서 수백만 개의 사이트, Apache 문서, 버그 보고서 및 디버깅 출력을 읽은 후 마침내 작동하게되었습니다. 아니요, 아직 소켓이있는 FPM은 지원 되지 않습니다. 기본 데비안 설정은 한동안 소켓을 사용하고 있었으므로 데비안 사용자도 그 설정을 변경해야합니다.

다음은 CakePHP 사이트와 PHPMyAdmin에서 작동하는 것입니다 (데비안 패키지를 사용하는 경우 후자가 약간의 구성이 필요합니다). 그래서 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>

위의 호스트는 다음과 같이 루트의 .htaccess와 완벽하게 작동합니다.

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

나는 당신이 의미하는 바를 정확히 얻지 못합니다 URL rewriting inside a subdirectory(루트의 index.php에만 다시 쓰고 있습니다).


(아, Xdebug가 시스템의 FPM과 충돌하지 않는지 확인해야합니다. 동일한 포트를 사용하려는 경우에 한해)


답변

당신이해야 할 모든 설정 :

 ProxyErrorOverride on

다음을 통해 고객 페이지를 설정하는 것을 잊지 마십시오.

ErrorDocument 404 /path/to/error_page_file

답변

이것이 내가 가진 것입니다. 제대로 작동하는 것 같습니다. Drupal을 하위 디렉토리에 넣고 재 작성 작업, 디렉토리 색인 작업 및 PATH_INFO가 작동합니다.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} ^/((.*\.php)(/.*)?)$
RewriteCond %2 -f
RewriteRule . fcgi://127.0.0.1:9000/%1 [L,P]
RewriteOptions Inherit

다시 작성하지 않고 ( “If”등) 이와 같은 작업을 시도했지만 아무 작업도 수행 할 수 없습니다.

편집 : 공유 호스팅 공급자로 이것을 구현하는 경우 이것은 보안 문제 일 수 있습니다. 사용자가 PHP 스크립트를 임의의 fcgi 프록시로 전달할 수 있습니다. 모든 사용자에 대해 별도의 풀이있는 경우 권한 상승 공격이 허용됩니다.


답변

또 다른 솔루션 (Apache> = 2.4.10 필요)-호스트 내부 :

# define worker
<Proxy "unix:/var/run/php5-fpm-wp.bbox.nuxwin.com.sock|fcgi://domain.tld" retry=0>
    ProxySet connectiontimeout=5 timeout=7200
</Proxy>

<If "%{REQUEST_FILENAME} =~ /\.php$/ && -f %{REQUEST_FILENAME}">
    SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
    SetHandler proxy:fcgi://domain.tld
</If>

따라서 여기서 PHP 용 fcgi 핸들러는 파일이 존재하고 파일 이름이 PHP 파일 확장자와 일치하는 경우에만 설정됩니다.

BTW : ProxyErrorOverrideOn 으로 설정하려는 아이디어를 가진 사람들에게는 이것이 실제로 나쁜 아이디어라는 것을 명심하십시오. 이 지시문의 사용법은 문제를 일으키지 않습니다. 예를 들어, 503과 같은 HTTP 코드를 보내는 PHP 응용 프로그램은 예기치 않은 결과를 초래할 수 있습니다. 기본 오류 처리기는 API를 제공하는 모든 경우와 PHP 응용 프로그램과 관련이 있으며 이는 실제로 나쁜 동작입니다.


답변

이를 해결하는 가장 좋은 방법은 mod_proxy 및 mod_rewrite 및 php-fpm에 대한 디버깅 로그를 설정하는 것입니다. Apache 2.4에서는 특정 모듈에 대해서만 디버깅 로그를 켤 수 있습니다.
http://httpd.apache.org/docs/current/mod/core.html#loglevel
모듈 및 디렉토리 별 구성은 Apache HTTP Server 2.3.6 이상에서 사용 가능합니다.

디렉토리에 이중 슬래시가 표시됩니까?

여기 내가 사용하는 것이 있으며 정상적으로 작동합니다.

<LocationMatch ^(.*\.php)$>
  ProxyPass fcgi://127.0.0.1:9000/home/DOMAINUSER/public_html$1
</LocationMatch>

답변

이 문제를 처리 할 때 내가 만난 한 가지는 다음 조합을 사용하는 것입니다.

chroot = /path/to/site
chdir = /

fpm 풀 구성에서 ProxyPass지시문 의 전체 경로를 전달하지 마십시오 .

ProxyPass fcgi://127.0.0.1:9020/$1

그러나 해당 포트의 풀이 chroot 된 경우 -ONLY-