+-
如何使用python的http.client准确读取一个响应块?
在 Python 3.3(或任何其他内置的python HTTP客户端库)中使用http.client,我如何一次只读取一个HTTP块的分块HTTP响应?

我正在扩展现有的测试夹具(使用http.client在python中编写),用于使用HTTP的分块传输编码写入其响应的服务器.为简单起见,假设我希望能够在客户端收到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客户端库?如果使用内置客户端lib无法实现,是否可以使用pip可安装模块?

最佳答案
更新:

分块传输编码的好处是允许传输动态生成的内容. HTTP库是否允许您读取单个块是一个单独的问题(参见RFC 2616 – Section 3.6.1).

我可以看到你试图做的是多么有用,但标准的python http客户端库没有你想要的东西而没有一些hackery(见http.client和httplib).

你试图做的可能适合在你的测试夹具中使用,但在野外没有任何保证.客户端读取的数据的分块可能与服务器发送的数据的分块不同.例如.数据可能在代理服务器到达之前被“重新分块”(见RFC 2616 – Section 3.2 – Framing Techniques).

诀窍是告诉响应对象它没有分块(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)
点击查看更多相关文章

转载注明原文:如何使用python的http.client准确读取一个响应块? - 乐贴网