falconry/falcon

Add support for setting resp.stream to a requests.Response or urllib3.HTTPResponse object

開放

#1,271 建立於 2018年5月12日

 (4 則留言) (0 個反應) (0 位負責人)Python (925 個分叉)batch import
documentationenhancementgood first issueneeds contributor

倉庫指標

星標
 (9,293 顆星)
PR 合併指標
 (平均合併 2天 7小時) (30 天內合併 9 個 PR)

描述

We already have support for streaming via a file-like project, but it is also common to fetch upstream resources via the requests library, and so it would be really helpful if Falcon supported this natively. Internally, the object can be tested to see if it is an instance of requests.Response or urllib3.HTTPResponse. These types can be optionally imported (and if the import fails, we know we never need to do this check).

Note that this requires passing stream=True when making the request (or preload_content=False when using urllib3 directly). This should be noted in the docstring for Response.stream.

One way of handling this would be to wrap the object in a closeable stream iterator and then return that to the WSGI server. Here's some proof of concept code (only tested on Python 3):

class CloseableStreamIterator(collections.Iterator):
    """Iterator that wraps a urllib3 response with support for release_conn().
    Args:
        resp (object): urllib3.HTTPResponse instance.
        block_size (int): Number of bytes to read per iteration (default 64K).
        decode_content (bool): If True, will attempt to decode the body
            according to the Content-Encoding header (default False).
    """

    __slots__ = [
        '_resp',
        '_stream',
    ]

    def __init__(self, resp, block_size=2**16, decode_content=False):
        self._resp = resp
        self._stream = resp.stream(amt=block_size, decode_content=decode_content)

    def __iter__(self):
        return self

    def __next__(self):
        return next(self._stream)

    def close(self):
        self._resp.release_conn()

貢獻者指南