NGINXでプロキシ応答のURLを書き換えるにはどうすればよいですか


87

私はmod_proxy_htmlでApacheを使用することに慣れており、NGINXで同様のことを達成しようとしています。具体的な使用例は、ルートコンテキストのサーバーのポート8080でTomcatで実行されている管理UIがあることです。

http://localhost:8080/

これをポート80で表示する必要がありますが、このホストで実行されているNGINXサーバーに他のコンテキストがあるため、次の場所でこれにアクセスしてみてください。

http://localhost:80/admin/

次の非常に単純なサーバーブロックでそれができることを期待していましたが、そうではありません。

server {
    listen  80;
    server_name screenly.local.akana.com;

    location /admin/ {
        proxy_pass http://localhost:8080/;
    }
}

問題は、返されるコンテンツ(html)にスクリプトへのURLとスタイル情報が含まれており、それらはすべてルートコンテキストでアクセスされるため、これらのURLを/ではなく/ admin /で始まるように書き換える必要があることです。

NGINXでこれを行うにはどうすればよいですか?

回答:


128

まず、proxy_passのドキュメントを注意深く完全に読む必要があります。

アップストリームサーバーに渡されるURIは、「proxy_pass」ディレクティブがURIで使用されているかどうかに基づいて決定されます。proxy_passディレクティブの末尾のスラッシュは、URIが存在し、に等しいことを意味し/ます。末尾にスラッシュがないということは、帽子のURIがないことを意味します。

URI付きProxy_pass

location /some_dir/ {
    proxy_pass http://some_server/;
}

上記では、次のプロキシがあります。

http:// your_server/some_dir/ some_subdir/some_file ->
http:// some_server/          some_subdir/some_file

基本的に、/some_dir/はに置き換えられ/、リクエストパスをから/some_dir/some_subdir/some_fileに変更し/some_subdir/some_fileます。

URIなしのProxy_pass

location /some_dir/ {
    proxy_pass http://some_server;
}

2番目の場合(末尾のスラッシュなし):プロキシは次のようになります:

http:// your_server /some_dir/some_subdir/some_file ->
http:// some_server /some_dir/some_subdir/some_file

基本的に、元の完全な要求パスは変更なしで渡されます。


したがって、あなたの場合、必要なものを取得するには、末尾のスラッシュを削除する必要があるようです。


警告

自動書き換えは、proxy_passで変数を使用しない場合にのみ機能することに注意してください。変数を使用する場合は、自分で書き直す必要があります。

location /some_dir/ {
  rewrite    /some_dir/(.*) /$1 break;
  proxy_pass $upstream_server;
}

書き換えが機能しない場合もあります。そのため、ドキュメントを読む必要があります。


編集

あなたの質問をもう一度読んで、あなたがhtml出力を編集したいだけだと私は見逃したようです。

そのためには、sub_filterディレクティブを使用できます。何かのようなもの ...

location /admin/ {
    proxy_pass http://localhost:8080/;
    sub_filter "http://your_server/" "http://your_server/admin/";
    sub_filter_once off;
}

基本的に、置き換えたい文字列と置き換え文字列


2
おかげで、それは大いに役立ちます。sub_filterがそれを行うと思います。
IanG 2015

2
私はnginxがすでに出力をどの程度書き換えているかを知りたいのですが、少なくともリンクにホスト/ホスト名を書き換える必要はありませんか?たとえば、sub_filter "http://localhost/" "http://localhost/admin/"
そうですね

1
text/htmlmimetype以外の書き換えを可能にするために、も追加する必要がありましたsub_filter_types *;
anttikoo 2017

このソリューションで何か奇妙なことが起こっています。リソース(* .js、*。cssなどがフェッチされています)が、ページのロードに失敗します。proxy_pass中http://your_server/admin/に解決されることを期待しますが、解決されhttp://your_serverreact-router /admin/ location did not match any routes、アプリケーションが「/ admin」について何も知らないため、アプリケーションでエラーが発生します。
プラチ2017年

また、応答によって送信されるヘッダーもURLに従って修正されるproxy_redirectように、ディレクティブを追加する必要がある場合がありますLocation。:このチュートリアルチェックアウトcyberciti.biz/faq/...
vivanov

22

データ圧縮を使用するバックエンドサーバーの最初の「sub_filter」の前に、次のディレクティブを設定する必要がある場合もあります。

proxy_set_header Accept-Encoding "";

そうしないと、機能しない可能性があります。あなたの例では、次のようになります。

location /admin/ {
    proxy_pass http://localhost:8080/;
    proxy_set_header Accept-Encoding "";
    sub_filter "http://your_server/" "http://your_server/admin/";
    sub_filter_once off;
}

-1

次のnginx構成例を使用できます。

upstream adminhost {
  server adminhostname:8080;
}

server {
  listen 80;

  location ~ ^/admin/(.*)$ {
    proxy_pass http://adminhost/$1$is_args$args;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $server_name;
  }
}

1
なぜこれが反対票を投じられるのですか?コードに問題はありますか?私には、後でポップアップするアプリをプロキシする際のいくつかの警告を解決する、素晴らしく複雑なソリューションのように思えます。理由はproxy_redirect off;わかりませんが。また、追加しproxy_set_header X-Forwarded-Proto $scheme;ます。
LUH
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.