nginx proxy_passでパスを削除する方法


77

で実行中のWebアプリケーションがありhttp://example.com/、別のアプリケーションを別のサーバーに「マウント」したいhttp://example.com/en。アップストリームサーバーで動作してproxy_passいるようですが、1つの問題があります:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

開くとexample.com/en、私のアップストリームアプリケーションが戻ります404 not found /en。アップストリームにはpathがないため、これは理にかなっています/en

あるproxy_path適切なソリューションは?/enルートパスとして代わりにリッスンするように「上流」を書き換える必要がありますか?または、アップストリームに渡されるパスを書き換えることができるディレクティブがありますか?

回答:


133

これは、正規表現を使用せずに、必要なことを行う最も効率的な方法です。

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

1
私の知る限り、最後の部分はまだプロキシに沿ったパスとして「/ en」を渡しますか?
バーク

15
@berkes、いいえ、proxy_pass違います-末尾のスラッシュが違いを生みます。また、この答えは、それはまた、それは保証しているため、あなたが思い付いたものよりも正確であるproxy_redirectにとどまるdefaultあなたはまだ使用することができ、ので、302あなたのバックエンド内らを、そしてそれはどこでも正常に動作しています。
cnst

4
ああ、末尾のスラッシュがありませんでした:(
Vanuan

3
ああ!トレーリングスラッシ!
バリーマック

4
3時間の検索、そしてええ...それは最後のスラッシュでした。相棒、ありがとな!
ルーカスP.

12

人気が高まっている新しい正規表現ベースの回答に対処したいと思います。

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

一見するとこのソリューションはよりキュートに見えるかもしれませんが、いくつかの理由で間違っています。

  • 上記の正規表現は、リクエストuriに一致し、/enjoyそれを/joyアップストリームにリダイレクトします。これは本当に意図したものですか?

  • のリクエストは/enリダイレクトを発生させず/、アップストリームから直接サービスを提供します(/en/代わりにリクエストが行われたかのように見えますが、完全ではありません)。ルートページのアップストリーム内で相対URIを使用する場合(そうでない場合/en/、アップストリームURI内に接頭辞がないのはなぜですか)、たとえばsrc="style.css"(言語固有の参照url("menu.png")など)、ブラウザはそれを要求しますの/style.css代わりに/en/style.css。(または、どこでも絶対URIを使用している場合でも、誰かが曖昧なセミオプションリソースを比較的参照している場合はどうでしょうか?)おっと、サイトが機能しないことがあります。

  • 私ごととしてすでにOP自身の答えで述べた別の質問では、以前のアドバイス正規表現を使用して、防止proxy_redirectのデフォルト値を持っていることからディレクティブをdefaultにそれを下げて、off代わりに。これは、アップストリームがLocation: http://127.0.0.1:8080/en/dir/リクエスト/en/dirが行われたときに応答する場合、それがクライアントに表示されることを意味し、明らかに正しく動作しません。(/enそもそも正規表現の使用を促す要求に対しては特に皮肉なことでしたが、この特定の実装は、すでに前述したように別の問題に苦しんでいます。)さらに、既に使用している場合upstream特に、複数のアップストリームサーバーがある場合は、カスタムサーバーを使用しようとすると、余分なextraいものになる可能性がありますproxy_redirect。内proxy_redirectで正規表現を使用して、おそらく任意のホストに一致させることもできますが、将来クロスドメインリダイレクトを行うことにした場合はどうなりますか?

単一の正規表現ベースの場所で上記のポイントのいくつかに対処するために、次のことができます(より簡単にするためにproxy_passupstream-basedディレクティブからサーバーへの参照も削除する必要があることに注意してくださいproxy_redirect):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

したがって、私に尋ねると、2つの兄弟の最上位の場所持つ元の解決策は、代わりに正規表現のルートをたどってウサギの穴に掘るよりも良いアイデアです。


これは、例外が発生しますnginx: [emerg] location "/en" is outside location "^/en/?((?<=/).*
Athlan

1
@Athlan、それはそもそもそれを実際に使うべきではないからです!それでもやりたい場合は、その場所を正規表現の外に置くことができます。
cnst

ローカリゼーション= / enを外部に置くことは本当にうまくいきます おかげで
セバスチャンウェバー

7

だから、私はstackoverflowに関する答えを見つけました:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

基本的に、正規表現を場所に渡し、backrefをproxy_pass URLに渡します。


「proxy_pass luscious / $ ;」と思います 「proxy_pass luscious / $ 2」である必要があります
Zafer

1
@Zaferは正しい、上記の答えは私にエラーを与えていた
フランク

答えを変更しましたが、これを試すことができるATMが手元にないので、確認されていません。
バーク

0

Nginxドキュメントへの会計

要求をHTTPプロキシサーバーに渡すには、場所内にproxy_passディレクティブを指定します。例えば:

location /some/path/ {
    proxy_pass http://www.example.com/link/;
}

この構成例では、この場所で処理されたすべての要求が、指定されたアドレスのプロキシサーバーに渡されます。このアドレスは、ドメイン名またはIPアドレスとして指定できます。アドレスにはポートも含まれる場合があります。

location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}

上記の最初の例では、プロキシされるサーバーのアドレスの後にURI、/ link /が続くことに注意してください。URIがアドレスとともに指定されている場合、locationパラメーターと一致する要求URIの部分を置き換えます。たとえば、ここでは/some/path/page.html URIを含むリクエストはhttp://www.example.com/link/page.htmlにプロキシされます。URIなしでアドレスが指定されている場合、または置き換えられるURIの部分を判別できない場合、完全な要求URIが渡されます(変更されている可能性があります)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.