Iterable对象和Django StreamingHttpResponse

Fel*_*oni 6 python django python-3.x django-2.0

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

我使用的是python 3.6,django 2.0 http.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
Run Code Online (Sandbox Code Playgroud)

响应是空的,我用以下方法测试迭代器:

b''.join(HTTPStreamIterAndClose(serv.connection, res, 200)
Run Code Online (Sandbox Code Playgroud)

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

Krz*_*arz 4

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

\n
\n

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

\n
    \n
  • 客户必须会说话HTTP/1.1或较新
  • \n
  • 请求方法为\xe2\x80\x99tHEAD
  • \n
  • 响应不包含Content-Length标头
  • \n
  • 响应状态为\xe2\x80\x99t204304
  • \n
\n
\n
\n

如果这些条件成立,那么 Gunicorn 将添加一个Transfer-Encoding: chunked在响应中添加一个标头,向客户端发出信号,表明响应将以块形式传输。

\n

事实上,Gunicorn 会做出回应Transfer-Encoding: chunked如果这些条件成立,即使\n您使用了 HttpResponse,Gunicorn 也会做出响应!

\n

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

\n
\n

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

\n

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

\n