Flaskアプリがマシンでローカルに実行されている別のWebサービスにリクエストをプロキシしたい。代わりにFlaskこれよりも高い-アプリに組み込まれている既存の認証システムを再利用できるように、レベルnginxインスタンス。この「シングルサインオン」を維持できるほど、優れています。
これを行うための既存のモジュールまたは他のコードはありますか? Flaskアプリをhttplibやurllibのようなものに橋渡しすることは、苦痛であることが判明しています。
Werkzeugベースのアプリでhttplibを使用してプロキシを実装しています(あなたの場合と同様に、webappの認証と承認を使用する必要がありました)。
Flask docsにはHTTPヘッダーへのアクセス方法が記載されていませんが、request.headers
を使用できます( Werkzeugのドキュメント を参照してください)。応答を変更する必要があり、プロキシされたアプリで使用されるヘッダーは予測可能であり、プロキシは簡単です。
応答を変更する必要がない場合は、werkzeug.wsgi.wrap_file
を使用してhttplibの応答ストリームをラップする必要があることに注意してください。これにより、最適なパフォーマンスを得るために、開いているOSレベルのファイル記述子をHTTPサーバーに渡すことができます。
私はこれと同じことを行うのにかなりの時間を費やし、結局、うまく機能しているように見えるrequestsライブラリを使用した解決策を見つけました。複数のCookieの設定を1回の応答で処理することもできるため、調査には少し時間がかかりました。 flaskビュー関数です:
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
私の当初の計画は、公開URLをhttp://www.example.com/admin/myapp
へのプロキシhttp://myapp.internal.example.com/
。その道を下って狂気を導きます。
ほとんどのWebアプリケーション、特に自己ホスト型のWebアプリケーションは、HTTPサーバーのルートで実行されることを想定しており、絶対パスで他のファイルを参照するなどのことを行います。これを回避するには、場所ヘッダーとHTML、JavaScript、CSSファイルのすべての場所でURLを書き換える必要があります。
私はやりました これを実行したFlaskプロキシブループリント を書きました、そしてそれは私が本当にプロキシしたい1つのwebappには十分に機能しましたが、持続可能ではありませんでした。正規表現の大きな混乱。
最後に、nginxに新しい仮想ホストをセットアップし、独自のプロキシを使用しました。どちらもホストのルートにあるため、URLの書き換えはほとんど不要です。 (そして、ほとんど必要ではなかったのに、nginxのプロキシモジュールが処理しました。)プロキシされているWebアプリケーションは、今のところ十分な独自の認証を行います。