繁体   English   中英

如何使用 python 的 http.client 准确读取一个响应块?

[英]How can I read exactly one response chunk with python's http.client?

在 Python 3.3+(或任何其他内置的 Python HTTP 客户端库)中使用http.client ,我如何才能一次读取一个分块的 HTTP 响应,而该响应恰好是一个 HTTP 块?

我正在为使用 HTTP 的分块传输编码写入其响应的服务器扩展现有的测试夹具(使用http.client用 python 编写)。 为了简单起见,假设我希望能够在客户端接收到 HTTP 块时打印一条消息。

我的代码遵循一个相当标准的模式来读取大量响应:

conn = http.client.HTTPConnection(...)
conn.request(...)
response = conn.getresponse()

resbody = []

while True:
    chunk = response.read(1024)
    if len(chunk):
        resbody.append(chunk)
    else:
        break

conn.close();

但是无论服务器是发送 10 字节块还是 10MiB 块,这都会读取 1024 字节块。

我正在寻找的是以下内容:

while True:
    chunk = response.readchunk()
    if len(chunk):
        resbody.append(chunk)
    else
        break

如果http.client无法做到这一点,是否可以使用另一个内置的 http 客户端库? 如果无法使用内置客户端库,是否可以使用pip可安装模块?

我发现像这样使用请求库更容易

r = requests.post(url, data=foo, headers=bar, stream=True)

for chunk in (r.raw.read_chunked()):
    print(chunk)

更新:

分块传输编码的好处是允许传输动态生成的内容。 HTTP 库是否允许您读取单个块是一个单独的问题(请参阅RFC 2616 - 第 3.6.1 节)。

我可以看到您尝试做的事情会有用,但是标准的 python http 客户端库在没有一些骇客的情况下不会做您想做的事情(请参阅http.clienthttplib )。

您尝试做的事情可能适用于您的测试夹具,但在野外并不能保证。 客户端读取的数据的分块可能与服务器发送的数据的分块不同。 例如,数据可能在到达之前已经被代理服务器“重新分块”(参见RFC 2616 - 第 3.2 节 - 成帧技术)。


诀窍是告诉响应对象它没有被分块( resp.chunked = False ),以便它返回原始字节。 这允许您在每个块返回时解析它的大小和数据。

import http.client

conn = http.client.HTTPConnection("localhost")
conn.request('GET', "/")
resp = conn.getresponse()
resp.chunked = False

def get_chunk_size():
    size_str = resp.read(2)
    while size_str[-2:] != b"\r\n":
        size_str += resp.read(1)
    return int(size_str[:-2], 16)

def get_chunk_data(chunk_size):
    data = resp.read(chunk_size)
    resp.read(2)
    return data

respbody = ""
while True:
    chunk_size = get_chunk_size()
    if (chunk_size == 0):
        break
    else:
        chunk_data = get_chunk_data(chunk_size)
        print("Chunk Received: " + chunk_data.decode())
        respbody += chunk_data.decode()

conn.close()
print(respbody)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM