Nginx httpsの書き換えによりPOSTがGETになります


17

私のプロキシサーバーはIP Aで実行され、これが人々が私のWebサービスにアクセスする方法です。nginx構成は、IP Bの仮想マシンにリダイレクトします。

IP Aのプロキシサーバーの場合、これは自分のサイトで利用可能です。

server {
        listen 443;
        ssl on;
        ssl_certificate nginx.pem;
        ssl_certificate_key nginx.key;

        client_max_body_size 200M;
        server_name localhost 127.0.0.1;
        server_name_in_redirect off;

        location / {
                proxy_pass http://10.10.0.59:80;
                proxy_redirect http://10.10.0.59:80/ /;

                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

}

server {
        listen 80;
        rewrite     ^(.*)   https://$http_host$1 permanent;
        server_name localhost 127.0.0.1;
        server_name_in_redirect off;
        location / {
                proxy_pass http://10.10.0.59:80;
                proxy_redirect http://10.10.0.59:80/ /;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

これproxy_redirectは、どのようにしてnginxを書き換えてHTTP POSTリクエストを転送するのですか?

書き換えのため、パブリックIPにヒットするものはすべて443にヒットします。内部的には、仮想マシンで80に転送しています。

しかし、設定をテストするために以下のようなPythonスクリプトを実行すると

import requests

data = {'username': '....', 'password': '.....'}
url = 'http://IP_A/api/service/signup'

res  = requests.post(url, data=data, verify=False)
print res
print res.json
print res.status_code
print res.headers

私は取得してい405 Method Not Allowedます。nginxでは、内部サーバーにヒットするGETと、元のヘッダーで実行したにもかかわらず、内部nginxがリクエストを取得していることがわかりましたPOST(これはPythonスクリプトで表示されました)。

書き換えには問題があるようです。これを修正する方法はありますか?書き直しをコメントアウトしたとき、確かに80に達し、それが通過しました。書き換えは内部サーバーと通信できるため、書き換え自体に問題はありません。これは、ドロップされたばかりの書き換えだPOSTGET

ありがとうございました!

(これは重要なブロッカーなので、これはNginxフォーラムでも尋ねられます...)

回答:


8

それはNginxではなく、あなたのブラウザです。

RFC2616の注:

RFC 1945およびRFC 2068は、クライアントがリダイレクトされた要求のメソッドを変更することを許可しないことを指定しています。ただし、ほとんどの既存のユーザーエージェントの実装では、302を303応答であるかのように扱い、Location [..]でGETを実行します。

これはすべての一般的なブラウザに当てはまり、あなたがそれについてできることは何もありません。


@ c2h50h HTTP仕様にそのようなものが記載されていることを理解しています。しかし、Nginxでは何ができますか?私は、これは内部80ポートへの前方443人が、彼らはまだやることができますささいな設定であることを意味しPUTPOSTDELETEGET。私の以前のセットアップでは、群衆にサービスを提供するフロントにこの余分なプロキシがありませんでした。同じ内部サーバー(テストサーバー)で同じ構成を使用しました。それはうまくいきます。
CppLearner

なし。100%クライアント側です。Webサーバー(任意のWebサーバー)が301または302リダイレクトを返す場合、クライアント側のブラウザーは、へのあらゆるタイプの要求を置き換えますGET。サーバー側の設定も、返されるhttpヘッダーも変更しません。歴史的な理由からそうです(誤解のために初期のブラウザはそのように動作し、事実上の標準になりました)。
c2h5oh

まあ、これは実際にはブラウザではありません。さて、HTTPプロトコルを使用しているため、ブラウザと言えます。しかし、この2層構成を実行していた場合にのみ、このようになるようです。同じ構成を内部マシンに直接配置し、そこでテストを実行しても、文句は言われません。しかし、再び、人々は彼らの制作でどのようにそれをしますか?一部の人々は、80だけを実行しているVMに対して443を逆にして、同様のことをしていると思います。より良い練習があれば、それを学び、それについて聞きたいです。
CppLearner

1
ブラウザとは、HTTPクライアントを意味し、すべての一般的なクライアントPOSTは、GET301または302リダイレクトされた場合になります。POSTはプロキシリダイレクトではPOSTのままですが、書き換えではPOSTになりません。
c2h5oh

1
再びRFC2616:If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.他のHTTPクライアントに関しては、その動作がどうなるか推測することさえできないため、ほとんどのブラウザは警告メッセージをポップアップします。
c2h5oh

1

私が使用POST /api/brandしてGET /api/brandいたWebアプリケーション(flask-restful)が「無効な」リクエストを行っていたため、変換されていました。使用した場合POST /api/brand/(末尾に注意してください/)、成功しました。


私はdjango rest-authログインをテストするためにPostmanを使用していましたが、説明されているのと同じ問題を見ていました。重要なのは、POSTリクエストの末尾の「/」を無視していたことです。
スティーブL
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.