47

我正在尝试使用 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(a requests.models.Response),但这失败了

TypeError: 'Response' object is not callable

是否有另一种简单的方法requests.models.Response从 Flask 返回一个?

4

5 回答 5

77

好的,找到了:

如果返回元组,则元组中的项目可以提供额外信息。这样的元组必须采用(响应、状态、标题)的形式。状态值将覆盖状态代码,并且标头可以是附加标头值的列表或字典。

烧瓶文档。)

所以

return (resp.text, resp.status_code, resp.headers.items())

似乎可以解决问题。

于 2013-10-24T14:43:09.510 回答
14

如果服务器返回编码数据(例如)并且您返回未更改的标头,则使用对象的textorcontent属性Response将不起作用。content-encoding: gzip发生这种情况是因为textcontent已被解码,因此标头报告的编码与实际编码之间将存在不匹配。

根据文档

在极少数情况下,您想从服务器获取原始套接字响应,您可以访问r.raw. 如果您想这样做,请确保您stream=True在初始请求中进行了设置。

Response.raw是一个原始的字节流——它不会转换响应内容。

因此,以下内容也适用于压缩数据:

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()
于 2018-10-17T12:00:12.693 回答
2

Flask 可以返回类型为 的对象flask.wrappers.Response

requests.models.Response您可以像这样从您的对象创建其中之一r

from flask import Response

return Response(
    response=r.reason,
    status=r.status_code,
    headers=dict(r.headers)
)
于 2020-10-09T11:55:49.730 回答
1

我遇到了同样的情况,除了在我的情况下,我的 requests.models.Response 包含一个附件。这就是我让它工作的方式:

return send_file(BytesIO(result.content), mimetype=result.headers['Content-Type'], as_attachment=True)

于 2017-08-13T06:45:24.907 回答
0

我的用例是在我自己的 Flask API 中调用另一个 API。我只是requests.get通过我的 Flask 响应传播不成功的调用。这是我成功的方法:

headers = {
    'Authorization': 'Bearer Muh Token'
}
try:
    response = requests.get(
        '{domain}/users/{id}'\
            .format(domain=USERS_API_URL, id=hit['id']),
        headers=headers)
    response.raise_for_status()
except HTTPError as err:
    logging.error(err)
    flask.abort(flask.Response(response=response.content, status=response.status_code, headers=response.headers.items()))
于 2020-02-17T23:04:37.957 回答