Flaskとリクエストを使用して単純なプロキシを構築しようとしています。コードは次のとおりです。
@app.route('/es/<string:index>/<string:type>/<string:id>',
methods=['GET', 'POST', 'PUT']):
def es(index, type, id):
elasticsearch = find_out_where_elasticsearch_lives()
# also handle some authentication
url = '%s%s%s%s' % (elasticsearch, index, type, id)
esreq = requests.Request(method=request.method, url=url,
headers=request.headers, data=request.data)
resp = requests.Session().send(esreq.prepare())
return resp.text
これは機能しますが、Elasticsearchからのステータスコードが失われます。 resp
(requests.models.Response
)を直接返そうとしましたが、これは失敗します
TypeError: 'Response' object is not callable
Flaskからrequests.models.Response
を返す別の簡単な方法はありますか?
わかりました、見つけました:
タプルが返される場合、タプル内のアイテムは追加情報を提供できます。このようなタプルは、少なくとも1つの項目がタプルにある必要がある形式(応答、ステータス、ヘッダー)である必要があります。ステータス値はステータスコードをオーバーライドし、ヘッダーは追加のヘッダー値のリストまたは辞書にすることができます。
( Flask docs 。)
そう
return (resp.text, resp.status_code, resp.headers.items())
トリックをするようです。
サーバーがエンコードを返した場合、 text
オブジェクトのcontent
またはResponse
プロパティを使用しても機能しません。データ(content-encoding: gzip
など)で、ヘッダーを変更せずに返します。これは、text
とcontent
がデコードされているために発生します。そのため、ヘッダーで報告されたエンコードと実際のエンコードが一致しなくなります。
ドキュメント によると:
サーバーから生のソケットレスポンスを取得したいというまれなケースでは、
r.raw
にアクセスできます。これを行う場合は、最初のリクエストでstream=True
を必ず設定してください。
そして
Response.raw
はバイトの生ストリームであり、応答コンテンツを変換しません。
そのため、以下はgzip圧縮されたデータでも機能します。
esreq = requests.Request(method=request.method, url=url,
headers=request.headers, data=request.data)
resp = requests.Session().send(esreq.prepare(), stream=True)
return resp.raw.read(), resp.status_code, resp.headers.items()
get
などのショートカットメソッドを使用する場合、次のようになります。
resp = requests.get(url, stream=True)
return resp.raw.read(), resp.status_code, resp.headers.items()
私の場合、requests.models.Responseに添付ファイルが含まれていたことを除いて、同じシナリオに遭遇しました。これは私がそれを機能させる方法です:
return send_file(BytesIO(result.content)、mimetype = result.headers ['Content-Type']、as_attachment = True)