Flaskアプリに対して行われたリクエストを、マシン上でローカルに実行されている別のWebサービスにプロキシしたいと思います。アプリに組み込まれている既存の認証システムを再利用できるように、高レベルのnginxインスタンスよりもFlaskを使用したいと思います。この「シングルサインオン」を維持できるほど、優れています。
これを行うための既存のモジュールまたは他のコードはありますか?Flaskアプリをhttplibやurllibのようなものにブリッジしようとすると、苦痛になります。
私はこれと同じことにかなりの時間を費やし、最終的にはうまく機能しているように見えるリクエストライブラリを使用して解決策を見つけました。1つの応答で複数のCookieを設定することも処理しますが、これを理解するには少し調査が必要でした。フラスコビュー機能は次のとおりです。
from flask import request, Response
import requests
def _proxy(*args, **kwargs):
resp = requests.request(
method=request.method,
url=request.url.replace(request.host_url, 'new-domain.com'),
headers={key: value for (key, value) in request.headers if key != 'Host'},
data=request.get_data(),
cookies=request.cookies,
allow_redirects=False)
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for (name, value) in resp.raw.headers.items()
if name.lower() not in excluded_headers]
response = Response(resp.content, resp.status_code, headers)
return response
2021年4月の更新:RFC2616セクション13.5.1excluded_headers
で定義されているすべての「ホップバイホップヘッダー」を含める必要があります。
Werkzeugベースのアプリでhttplibを使用してプロキシを実装しています(あなたの場合のように、Webアプリの認証と承認を使用する必要がありました)。
FlaskのドキュメントにはHTTPヘッダーへのアクセス方法が記載されていませんが、使用できますrequest.headers
(Werkzeugのドキュメントを参照)。応答を変更する必要がなく、プロキシされたアプリで使用されるヘッダーが予測可能である場合、プロキシは簡単です。
応答を変更する必要がない場合は、を使用しwerkzeug.wsgi.wrap_file
てhttplibの応答ストリームをラップする必要があることに注意してください。これにより、最適なパフォーマンスを得るために、開いているOSレベルのファイル記述子をHTTPサーバーに渡すことができます。
私の当初の計画は、公開URLをにhttp://www.example.com/admin/myapp
プロキシするようなものにすることでしたhttp://myapp.internal.example.com/
。その道を下って行くと狂気につながります。
ほとんどのWebアプリケーション、特に自己ホスト型Webアプリケーションは、HTTPサーバーのルートで実行されることを想定しており、絶対パスで他のファイルを参照するようなことを行います。これを回避するには、場所のヘッダーとHTML、JavaScript、CSSファイルなどのURLをあちこちで書き直す必要があります。
私はこれを行うFlaskプロキシブループリントを作成しました。これは、私が本当にプロキシしたい1つのWebアプリには十分に機能しましたが、持続可能ではありませんでした。それは正規表現の大きな混乱でした。
最後に、nginxに新しい仮想ホストをセットアップし、独自のプロキシを使用しました。どちらもホストのルートにあるため、URLの書き換えはほとんど不要でした。(そして、ほとんど必要なかったのは、nginxのプロキシモジュールが処理したことです。)プロキシされるWebアプリは、今のところ十分な独自の認証を行います。