从Flask返回一个requests.Response对象

时间:2013-10-24 14:37:29

标签: python proxy flask python-requests

我正在尝试使用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的状态代码。我尝试直接返回resprequests.models.Response),但是

失败了
TypeError: 'Response' object is not callable

还有另一种简单的方法可以从Flask返回requests.models.Response吗?

5 个答案:

答案 0 :(得分:54)

好的,找到了:

  

如果返回元组,则元组中的项可以提供额外信息。这样的元组必须采用(响应,状态,标题)形式,其中至少有一个项目必须在元组中。状态值将覆盖状态代码,标题可以是其他标题值的列表或字典。

Flask docs。)

所以

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

似乎可以解决问题。

答案 1 :(得分:4)

如果服务器返回编码后的数据(例如text)并且您返回的标头保持不变,则无法使用Response对象的contentcontent-encoding: gzip属性。发生这种情况是因为textcontent已被解码,因此标头报告的编码和实际编码之间将不匹配。

根据the documentation

  

在极少数情况下,您想从服务器获取原始套接字响应,则可以访问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()

答案 2 :(得分:2)

Flask可以返回d = {'Ernst & Young Nederland LLP': ['Mar 5 06:49:10 2021 GMT', '2048']} for v in d.values(): print(v[0]) 类型的对象。

您可以像这样从flask.wrappers.Response对象requests.models.Response创建其中之一:

r

答案 3 :(得分:0)

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

  

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

答案 4 :(得分:0)

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

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()))