Nginxの複数の場所の問題


14

現在、1つのリポジトリから3つのアプリケーションを3つに分割しようとしていますが、URL構造は維持しているため、基本的に同じドメインの下の異なる場所を異なるアプリケーションで配信する必要があります。

私が苦労しているのは、アプリの1つが存在しないURLのフォールバックである必要があるため、最初のアプリが一致せず、2番目のアプリが一致しない場合、3番目がリクエストを処理する必要があるということです

私が持っている構造は次のとおりです。

/ etc / nginx / sites-enabled / main_site、ここでは、server_nameと私が手に入れたログは別として、include /etc/nginx/subsites-enabled/*3つの構成ファイルがあり、各アプリに1つずつあります。

3つの構成ファイルにはそれぞれ、場所ブロックが含まれています。

正規表現でネガティブな先読みを試みました(基本的に他のアプリが処理するURLをハードコードしようとしています)が失敗しました。

要約すると、

/および/ communityは、/ etc / nginx / subsites-enabled / example.org / home(いくつかのperlスクリプト)によって配信される必要があります

/ newsは/etc/nginx/subsites-enabled/example.org/news(wordpress)によって配信される必要があります

その他はすべて/etc/nginx/subsites-enabled/example.org/app(ケーキアプリ)で配信する必要があります

perlビットは正常に動作します。私が抱えている問題は、アプリがニュースを引き継いでいる(おそらく。静的アセットが機能しないなど)。

私の構成は次のとおりです。

/etc/nginx/sites-enabled/example.org:

server {
    listen   80;
    server_name example.org;
    error_log /var/log/nginx/example.org.log;

    include /etc/nginx/subsites-enabled/example.org/*;
}

/etc/nginx/subsites-enabled/example.org/home:

location = / {
  rewrite ^.*$ /index.pl last;
}

location ~* /community(.*) {
  rewrite ^.*$ /index.pl last;
}

location ~ \.pl {
  root   /var/www/vhosts/home;
  access_log /var/log/nginx/home/access.log;
  error_log /var/log/nginx/home/error.log;

  include /etc/nginx/fastcgi_params;
  fastcgi_index index.pl;
  fastcgi_param SCRIPT_FILENAME /var/www/vhosts/home$fastcgi_script_name;
  fastcgi_pass  unix:/var/run/fcgiwrap.socket;
}

/ etc / ngins / subsites-enabled / news

location /news {
  access_log /var/log/nginx/news/access.log;
  error_log /var/log/nginx/news/error.log debug;

  error_page 404 = /news/index.php;

  root /var/www/vhosts/news;

  index index.php;

  if (!-e $request_filename) {
      rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news$fastcgi_script_name;
  }
}

/ etc / nginx / subsites-enabled / app:

location ~ .* {
  access_log /var/log/nginx/app/access.log;
  error_log /var/log/nginx/app/error.log;

  rewrite_log on;

  index index.php;
  root /var/www/vhosts/app/app/webroot;

  if (-f $request_filename) {
    expires 30d;
    break;
  }

  if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot$fastcgi_script_name;
  }
}

a)構成を、さまざまなリダイレクト(存在しないURLのリダイレクトを含む)のいくつかの例とともに投稿します。b)デフォルトのアプリにマップする名前付きの場所ブロック(プレフィックスを使用)でtry_filesを使用@します。404を名前付きの場所にマップするerror_pageをセットアップすることもできます。
cyberx86

cyberx86 @私はより多くの詳細と私の設定を追加
アンドレイSerdeliuc

一目でわかること:a)正規表現の照合が従来の文字列より優先されるため、ニュースブロックの代わりにアプリブロックが一致する-try location ^~ /news。b)アプリのブロックについて、できるはずですlocation /(これはと同じではありませんが、location = /まだ一致していないすべてのものと一致する必要があります。c)場合によっては(特に正規表現)、順序が重要です-3ブロックを正しい順序で1つのファイルにまとめます。また、ではなくtry_filesを使用します!-e。最後にwiki.nginx.org/HttpCoreModule#locationを参照してください。
cyberx86

それらを単一のファイルに結合することを含め、それらのほとんどすべてのバリエーションを試してみました(それらは別々にデプロイされるので別々にする必要がありますが)、どれも機能しません。ニュースはアプリによって処理されるだけです。
アンドレイセルデリウ

まあ、私はそれを解決したと思います-私が最初に予想したよりも少しトリッキー-しかし確かにウィットと一致するのは楽しいです。パズルをありがとう。
cyberx86

回答:


45

設定にはいくつか問題があります。関連する2つは次のとおりです。

  1. ロケーションブロック内のパスには、一致したパスが含まれています。
  2. 「最後」のリライトは、一致するすべての利用可能な場所を調べることで継続します(現在の場所のブロックから抜け出します)。

たとえば、example.org / news / test.htmというURLを使用します

  • location /newsブロックは、それにマッチします
  • その場合、使用されるパスは/news/test.htm-ロケーションブロック内にあるという理由だけで変更されません
  • document_rootへのパスを追加すると、次のようになります。 /var/www/vhosts/news/news/test.htm
  • あなたのif (!-e $request_filename)文は、この存在しないファイルをキャプチャする必要があります
  • パスを書き換えます /index.php
  • lastプロセスを使用しているため、最初からやり直します(ロケーションブロックから抜け出します)
  • /index.phpは現在、によってキャプチャされていlocation /app blockます。

rootディレクティブを使用した上記の問題は、アプリのロケーションブロックに移動するとさらに悪化します。「news」ブロックとは異なり、「news」をパスから削除することも考えられます(再び追加されるため)、「webroot」で終わるアプリパスに対してこれを行うことはできません。

解決策はaliasディレクティブにあります。これはdocument_rootを変更しませんが、リクエストの処理に使用されるファイルパスを変更します。残念ながら、rewritetry_files予期しない動作をする傾向がありaliasます。

PHPではなく、HTMLとPerlブロックだけの単純な例から始めましょう。ただし、フォルダー構造はあなたのものと一致します(Nginx 1.0.12、CentOS 6でテスト済み):

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;

        [fastcgi_stuff...]
    }


    location ^~ /news {
        alias /var/www/vhosts/news;
        index index.htm;

        try_files $uri $uri/ /news/index.htm;
    }

    location ^~ /app {
        alias /var/www/vhosts/app/app/webroot;
        index index.htm;

        try_files $uri $uri/ /app/index.htm;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}
  • location = / -ルートパスのみに一致します
  • location ^~ /community -/ communityで始まるすべてのパスに一致します
  • location ~ \.pl -.plを含むすべてのファイルに一致します
  • location ^~ /news -/ newsで始まるすべてのパスに一致します
  • location ^~ /app -/ appで始まるすべてのパスに一致します
  • location / -上記と一致しないすべてのパスに一致します

^~- を削除できるはずですが、一致が見つかると検索が停止するため、パフォーマンスがわずかに改善される場合があります。

それはそこにあるバック、中にPHPブロックを追加することは簡単なことである必要がありますが、残念ながら、わずかな難しさ- try_files(とあなたのリライト)は、ネストされた場所のブロックに目的のパスを渡して終了していない-と使用してalias拡張子のみである場合、ロケーションブロックで指定されたものは機能しません。

解決策の1つは、エイリアスディレクティブと一緒にキャプチャを実行する個別のロケーションブロックを使用することです-それは非常にエレガントではありませんが、私が知る限り、それは動作します(再び、Nginx 1.0.12、CentOS 6でテスト-もちろん、私はCakePHP、Wordpress、Perlをセットアップしませんでした-各フォルダーでいくつかのPHPファイルとHTMLファイルを使用しました)

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;
        access_log /var/log/nginx/home.access.log;
        error_log /var/log/nginx/home.error.log;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.pl;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
    }

    location /news {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/news;
        index index.php;
        try_files $uri $uri/ /news/index.php;
    }

    location ~* ^/news/(.*\.php)$ {
        access_log /var/log/nginx/news.php.access.log;
        error_log /var/log/nginx/news.php.error.log notice;
        alias /var/www/vhosts/news/$1;
        try_files "" /news/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location /app {
        alias /var/www/vhosts/app/app/webroot;
        access_log /var/log/nginx/app.access.log;
        error_log /var/log/nginx/app.error.log notice;
        index index.php;
        try_files $uri $uri/ /app/index.php;
    }

    location ~* ^/app/(.*\.php)$ {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/app/app/webroot/$1;
        try_files "" /app/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}

上記の構成は、上記の単純な構成を取り、2つの変更を行います。

  • 2つのロケーションブロックを追加します。
    • location ~* ^/news/(.*\.php)$ -.phpで終わるすべてのファイルに一致し、パスは/ news /で始まります
    • location ~* ^/app/(.*\.php)$ -パスが/ app /で始まる.phpで終わるすべてのファイルに一致します
  • ^~マッチングを削除します-これは、追加された2つのロケーションブロックがパスと一致するために必要です(そうでない場合、/ newsまたは/ appブロックでマッチングが停止します)。

ここで、位置合わせの順序は非常に重要であることに注意してください。

  • 最初に完全一致(を使用=
  • ^~秒と一致
  • 正規表現ブロックの一致
  • 従来の文字列-一致する正規表現が見つからない場合のみ

一致する正規表現は、まっすぐな文字列に優先します!

重要なポイントは、キャプチャがエイリアスで使用される場合、先頭のフォルダだけでなく、URL全体が置き換えられることです。残念ながら、これはそれ$fastcgi_script_nameが空のままであることを意味します-そのため、$1代わりに上記を使用しました。

いくつかの変更を加える必要があると確信していますが、基本的な前提は機能するはずです。必要に応じてブロックを複数のファイルに分割できるはずです-順序は構成に影響しないはずです。


2
おい、100回賛成できたらいいな。あなたは純粋に素晴らしいです。ありがとう!
アンドレイセルデリウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.