構成の問題なのか、nginxのバグなのかわからない、奇妙な問題が発生しています。私のセットアップは、Apache2バックエンドサーバーを備えたnginxリバースプロキシです。ロードバランサーは、 wikiの例 に似た非常に基本的なものです。簡略化:
http {
upstream myproject {
server 127.0.0.1:8000;
}
server {
listen 80;
location / {
proxy_pass http://myproject;
}
}
}
ここで、たとえば、URLの末尾にスラッシュを付けずに、Apacheでディレクトリを要求しようとすると、問題が発生します。たとえば、クライアントは次のことを要求します。
http://Apache.myserver.com/somedirectory
ApacheはHTTP302で応答して、クライアントをにリダイレクトします
http://Apache.myserver.com/somedirectory/
URLの末尾にスラッシュがあり、ディレクトリであることを示していることに注意してください。また、Apacheは、リダイレクトヘッダーで着信要求のホスト名を使用することで「スマート」であることに注意してください。これまでのところすべて問題ありません。ただし、負荷分散でnginxを使用する場合、この301は、nginxアップストリーム名を実際のサーバー/ドメインに変換せずにクライアントに送信されます。したがって、クライアントは次のものを受け取ります。
GET http://nginx.myserver.com/somedirectory
HTTP 301 Moved Permanently
...
Location: http://myproject:8000/somedirectory/
myproject
は、nginxアップストリームバックエンドの名前です。クライアントが解決できるのは実際のホストではありません。代わりに、クライアントはにリダイレクトされるべきだったように私には思えます
http://nginx.myserver.com/somedirectory/
つまりアップストリームバックエンドの名前は、応答ヘッダーで置き換えられている必要があります。これはnginxのバグですか、それとも何か間違ったことをしていますか?
Nginxにはこの種の問題に対処するための プロキシリダイレクト オプションがたくさんあることがわかりました。私は次のようなものを使用することになりました:
location / {
proxy_pass http://myproject;
proxy_set_header Host myproject;
proxy_redirect http://myproject/ $scheme://$Host/;
proxy_redirect http://myproject:8000/ $scheme://$Host/;
}
これは基本的にアップストリーム名を$ Hostに置き換え、ポートを削除します。私の場合、HTTP/HTTPSのデフォルトポートでnginxをホストしているため、これは機能しました。 nginxがデフォルト以外のポートで実行されている場合は、次のようなものが必要です。
proxy_redirect http://myproject/ $scheme://$Host:$server_port/;
proxy_redirect http://myproject:8000/ $scheme://$Host:$server_port/;
次のように server_name_in_redirect を使用してみてください。
server_name_in_redirect off;
それが機能しない場合は、バックエンドが正しく動作しているように見えますが、 proxy_redirect で何かを行う必要があるかもしれません。