如何强制http.client在python中发送分块编码的HTTP主体?
我想发送分块的HTTP请求体来测试我自己的HTTP服务器。于是我写了这段Python代码:
import http.client
body = 'Hello World!' * 80
conn = http.client.HTTPConnection("some.domain.com")
url = "/some_path?arg=true_arg"
conn.request("POST", url, body, {"Transfer-Encoding":"chunked"})
resp = conn.getresponse()
print(resp.status, resp.reason)
我希望HTTP请求的内容是以分块的方式发送的,但我用Wireshark抓取网络数据包时发现,HTTP请求的内容并没有以分块的方式发送。
怎么才能通过Python的http.client库发送分块的请求体呢?
2 个回答
2
我建议,如果你已经知道你的数据大小,就像在这个回答中提到的那样,你可以直接设置Content-Length
,然后一次性把所有数据发送回去,这其实和你用conn.send
一次性发送的做法是一样的。
分块传输编码在你不知道数据大小的时候最有用,比如说动态生成的内容。我已经修改了你的代码来说明这一点:
import httplib
def write_chunk(conn, data):
conn.send("%s\r\n" % hex(len(data))[2:])
conn.send("%s\r\n" % data)
def dynamically_generate_data():
for i in range(80):
yield "hello world"
conn = httplib.HTTPConnection("localhost")
url = "/some_path"
conn.putrequest('POST', url)
conn.putheader('Transfer-Encoding', 'chunked')
conn.endheaders()
for new_chunk in dynamically_generate_data():
write_chunk(conn, new_chunk)
conn.send('0\r\n')
resp = conn.getresponse()
print(resp.status, resp.reason)
conn.close()
8
好的,我明白了。
首先,我需要自己写一个分块编码的函数。
然后用 putrequest()、putheader()、endheaders() 和 send() 来代替 request()。
import http.client
def chunk_data(data, chunk_size):
dl = len(data)
ret = ""
for i in range(dl // chunk_size):
ret += "%s\r\n" % (hex(chunk_size)[2:])
ret += "%s\r\n\r\n" % (data[i * chunk_size : (i + 1) * chunk_size])
if len(data) % chunk_size != 0:
ret += "%s\r\n" % (hex(len(data) % chunk_size)[2:])
ret += "%s\r\n" % (data[-(len(data) % chunk_size):])
ret += "0\r\n\r\n"
return ret
conn = http.client.HTTPConnection(host)
url = "/some_path"
conn.putrequest('POST', url)
conn.putheader('Transfer-Encoding', 'chunked')
conn.endheaders()
conn.send(chunk_data(body, size_per_chunk).encode('utf-8'))
resp = conn.getresponse()
print(resp.status, resp.reason)
conn.close()