web-dev-qa-db-ja.com

Nginxの場所で複数のプロキシエンドポイントを提供する

/apiの単一の場所からサービスを提供するAPIエンドポイントがいくつかあり、サブパスは異なるエンドポイントに移動しています。具体的には、webdisを/apiで、独自のAPIを/api/mypathで利用できるようにしたいと考えています。

Redisコマンド名と競合する可能性が低いサブパスを使用しており、APIの設計を完全に制御して競合を回避しているため、webdis APIとの競合について心配していません。

これは私がハッキングしてきた私のテストサーバーからの設定ファイルです:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # temporary hardcoded workaround
  location = /api/mypath/about {
    proxy_pass http://localhost:3936/v1/about;
  }

  location /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }

  # tried this but it gives "not found" error
  #location ^~ /api/mypath/ {
  #  rewrite ^/api/mypath/(.*)$ /$1 break;
  #  proxy_pass http://localhost:3936/v1/;
  #}
  #
  #location ^~ /api {
  #  rewrite ^/api/(.*)$ /$1 break;
  #  proxy_pass http://localhost:7379/;
  #}
}

回避策を変更して、/api/mypath/*へのリクエストがポート3936のエンドポイントに送信され、それ以外のすべてがポート7379に送信されるようにするにはどうすればよいですか?

14
hamstar

これを書き直す必要はありません。

server {
  ...

  location ^~ /api/ {
    proxy_pass http://localhost:7379/;
  }
  location ^~ /api/mypath/ {
    proxy_pass http://localhost:3936/v1/;
  }
}

nginxのドキュメント によると

場所は、プレフィックス文字列または正規表現のいずれかで定義できます。正規表現は、先行する~*修飾子(大文字と小文字を区別しないマッチングの場合)または~修飾子(大文字と小文字を区別するマッチングの場合)で指定されます。特定のリクエストに一致する場所を見つけるために、nginxは最初にプレフィックス文字列を使用して定義された場所(プレフィックスの場所)をチェックします。その中で、一致するプレフィックスが最も長い場所が選択され、記憶されます。次に、構成ファイルでの出現順に正規表現がチェックされます。正規表現の検索は最初の一致で終了し、対応する構成が使用されます。正規表現との一致が見つからない場合は、以前に記憶されたプレフィックスの場所の構成が使用されます。

最長の一致するプレフィックスの場所に^~修飾子がある場合、正規表現はチェックされません。

したがって、/api/mypath/で始まるすべてのリクエストは、2番目のブロックによって常に処理されます。これは、最長一致プレフィックスの場所だからです。

/api/で始まり、直後にmypath/が続かないリクエストは、常に最初のブロックによって処理されます。これは、2番目のブロックが一致しないため、最初のブロックが最長一致接頭辞の場所。

24
Alexey Ten

OKだとわかりました。「見つかりません」というエラーはnginxが原因であると考えていましたが、実際は私のAPIが原因でした。誰かが興味を持っているならこれが私の解決策です:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # automatically go to v1 of the (grape) API
  location ^~ /api/mypath/ {
    rewrite ^/api/mypath/(.*)$ /v1/$1 break;
    proxy_pass http://localhost:3936/;
  }

  location ^~ /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }
}
6
hamstar