web-dev-qa-db-ja.com

nginx try_files、proxy_passおよびアップストリーム

私はPHPアプリ用のドッキングされたテスト「プラットフォーム」を構築しています-特に(今のところ)WordPress用です。 PHPFarmを使用して、異なるバージョンのPHPを異なるポートで提供しています。 nginxを前に使って、私はそれの多くを動かしています。 ( https://github.com/richardtape/testit がメインのリポジトリです)

私が今直面している大きな問題は、WordPressの「かなりのパーマリンク」が機能することです。標準のnginxセットアップでは、これは次のようなケースにすぎません

location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
}

しかし、ホストマシンからニースのURLを取得できるようにするため、および1つのコードベースを取得するために、次の行に沿って何かを使用しています。

server {
    listen 80;
    index index.php index.html index.htm;
    server_name 52.spaces.dev;

    location / {

        proxy_pass http://phpfarm_52;
        proxy_set_header Host $Host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
    root /var/www;
}

upstream phpfarm_52{
    server phpfarm:8052;
}

これは、現状では機能します。 (PHP 5.3、5.4、5.5、5.6、7の場合、これと同様のルールがさらに5つあります)ホームページは、ホストマシンからさまざまなserver_nameのそれぞれにロードされます(そして、PHPバージョンで、異なるPHPバージョンを取得していることがわかります。

ただし、2番目に「内部」URLに切り替えます(または任意の非ルートすなわち http://52.spaces.dev/about/ ) 、404が表示されます。次のようなものを試しました

location / {
    try_files $uri $uri/ /index.php?$args
}

location ~ \.php$ {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $Host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

私が試したいくつかの異なる方法に応じて、リダイレクトループが発生します。これは、一連の301リダイレクトであり、ページが読み込まれないか、次のようなエラーが発生します。

nginx_1      | 2016/04/08 20:31:29 [error] 5#5: *4 rewrite or internal redirection cycle while processing "/index.php", client: 192.168.99.1, server: 52.spaces.dev, request: "GET /favicon.ico HTTP/1.1", Host: "52.spaces.dev", referrer: "http://52.spaces.dev/"

行き詰まっています。私はまた、nginx設定(かなり明白かもしれません)にかなり新しいので、私は何か完全に間違っているおよび/またはばかげているかもしれません。助言がありますか?

9
RichardTape

質問のリダイレクトループで発生している問題は、静的ファイルであっても、基本的にすべてのリクエストがindex.php?$ argsブロックを介してルーティングしようとすることです。

ここには2つの可能な解決策があります。最初に、単一のnginxインスタンスでnginxセットアップを実装する場合は、このスレッドを見てください: NGINX try_files with multiple named locations and this blog post http://linuxplayer.org/2013/06/nginx-try-files-on-multiple-named-location-or-server

発生する必要があるのは、リソースがアップストリームにそのまま存在する(つまり、404を返さない)かどうかを最初にテストする必要があることです。ある場合は、そのまま提供します。そうでない場合は、それをindex.phpのパラメーターとして配置しようとする書き換えブロックを呼び出します。だからあなたはこのようなものになってしまうでしょう(申し訳ありませんが、私はこれをテストする機会は本当にありませんが、うまくいけばアイデアが出ます):

location / {
    try_files $uri $uri/ @phpproxy;
}

location @phpproxy {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $Host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @rewrite_proxy;
}

location @rewrite_proxy {
    rewrite ^/(.*)$ /index.php?$1 break;
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $Host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

2番目の解決策(私が個人的に好みます)は、すべてのアップストリームの前に独自のnginxを配置することです。次に、他のすべての前面にある上位のnginxは、単純なproxy_pass(+おそらくいくつかの静的コンテンツ)を備えたよりすっきりとした構造になり、それだけです。アップストリームからの404を解決する必要がないため、リクエストの往復も削減されます。

9
taleodor