Flask で別の Web サービスにプロキシする 質問する

Flask で別の Web サービスにプロキシする 質問する

Flask アプリへのリクエストを、マシン上でローカルに実行されている別の Web サービスにプロキシしたいと考えています。アプリに組み込まれている既存の認証システムを再利用できるように、上位レベルの nginx インスタンスではなく Flask を使用したいと思います。この「シングル サインオン」を維持できればできるほど良いです。

これを行うための既存のモジュールまたは他のコードはありますか? Flask アプリを httplib や urllib のようなものにブリッジしようとすると、面倒なことが分かります。

ベストアンサー1

私はこれにかなりの時間を費やし、最終的にリクエストうまく機能するライブラリです。1 つの応答で複数の Cookie を設定する処理も実行できますが、これを理解するには少し調査が必要でした。以下は Flask のビュー関数です。

from dotenv import load_dotenv  # pip package python-dotenv
import os
#
from flask import request, Response
import requests  # pip package requests


load_dotenv()
API_HOST = os.environ.get('API_HOST'); assert API_HOST, 'Envvar API_HOST is required'

@api.route('/', defaults={'path': ''}, methods=["GET", "POST"])  # ref. https://medium.com/@zwork101/making-a-flask-proxy-server-online-in-10-lines-of-code-44b8721bca6
@api.route('/<path>', methods=["GET", "POST"])  # NOTE: better to specify which methods to be accepted. Otherwise, only GET will be accepted. Ref: https://flask.palletsprojects.com/en/3.0.x/quickstart/#http-methods
def redirect_to_API_HOST(path):  #NOTE var :path will be unused as all path we need will be read from :request ie from flask import request
    res = requests.request(  # ref. https://stackoverflow.com/a/36601467/248616
        method          = request.method,
        url             = request.url.replace(request.host_url, f'{API_HOST}/'),
        headers         = {k:v for k,v in request.headers if k.lower() != 'host'}, # exclude 'host' header
        data            = request.get_data(),
        cookies         = request.cookies,
        allow_redirects = False,
    )

    #region exlcude some keys in :res response
    excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']  #NOTE we here exclude all "hop-by-hop headers" defined by RFC 2616 section 13.5.1 ref. https://www.rfc-editor.org/rfc/rfc2616#section-13.5.1
    headers          = [
        (k,v) for k,v in res.raw.headers.items()
        if k.lower() not in excluded_headers
    ]
    #endregion exlcude some keys in :res response

    response = Response(res.content, res.status_code, headers)
    return response

2021年4月更新:excluded_headersおそらく、定義されるすべての「ホップバイホップヘッダー」を含める必要があります。RFC 2616 セクション 13.5.1

おすすめ記事