从Flask返回一个requests.Response对象

Fre*_*Foo 36 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
Run Code Online (Sandbox Code Playgroud)

这有效,除了它丢失了Elasticsearch的状态代码.我尝试直接返回resp(a requests.models.Response),但这失败了

TypeError: 'Response' object is not callable
Run Code Online (Sandbox Code Playgroud)

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

Fre*_*Foo 62

好的,发现它:

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

(Flask docs.)

所以

return (resp.text, resp.status_code, resp.headers.items())
Run Code Online (Sandbox Code Playgroud)

似乎可以做到这一点.

  • 使用`resp.content`而不是`resp.text`来处理二进制和文本响应 (13认同)
  • 返回值不需要括号。 (2认同)

Smi*_*Smi 8

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

根据文档

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

如果您使用的快捷方式,例如get

resp = requests.get(url, stream=True)
return resp.raw.read(), resp.status_code, resp.headers.items()
Run Code Online (Sandbox Code Playgroud)