6

我想用 django 连接到内部 http 服务,我需要缓冲这些服务的 http 响应的输出,因为有些内容非常大。

我正在使用 python 3.6、django 2.0http.client和以下代码:

class HTTPStreamIterAndClose():
    def __init__(self, conn, res, buffsize):
        self.conn = conn
        self.res = res
        self.buffsize = buffsize
        self.length = 1

        bytes_length = int(res.getheader('Content-Length'))

        if buffsize < bytes_length:
            self.length = math.ceil(bytes_length/buffsize)

    def __iter__(self):
        return self

    def __next__(self):
        buff = self.res.read(self.buffsize)

        if buff is b'':
            self.res.close()
            self.conn.close()

            raise StopIteration
        else:

            return buff

    def __len__(self):
        return self.length


def passthru_http_service(request, server, timeout, path):
    serv = HTTPService(server, timeout)
    res = serv.request(path)

    response = StreamingHttpResponse(
        HTTPStreamIterAndClose(serv.connection, res, 200),
        content_type='application/json'
    )
    response['Content-Length'] = res.getheader('Content-Length')

    return response

并且响应为空,我使用以下方法测试迭代器:

b''.join(HTTPStreamIterAndClose(serv.connection, res, 200)

一切正常,我不知道为什么不工作。

4

2 回答 2

4

https://andrewbrookins.com/django/how-does-djangos-streaminghttpresponse-work-exactly/

首先,必须满足一些条件:

  • 客户必须会说话HTTP/1.1或更新
  • 请求方法不是HEAD
  • 响应不包含Content-Length标头
  • 响应状态不是204304

如果这些条件为真,则 Gunicorn 将Transfer-Encoding: chunked在响应中添加一个标头,向客户端发出响应将分块传输的信号。

事实上,Transfer-Encoding: chunked即使你使用了 HttpResponse,Gunicorn 也会做出响应,前提是这些条件为真!

要真正流式传输响应,即将响应分段发送到客户端,条件必须为真,并且您的响应需要是具有多个项目的可迭代。

基本上,您需要决定:流式传输还是Content-Length.

如果您想要可恢复下载,请使用Range.

于 2018-01-05T13:56:28.333 回答
0

最后,问题在于http请求在几毫秒后断开连接,这就是为什么当我在连接之后和创建对象之前立即迭代时发现而不是在我在响应之后使用时,但是当我开始迭代时开始连接,一切正常=/。

干杯。

于 2018-01-15T21:35:47.097 回答