如何在 python 中强制 http.client 发送分块编码的 HTTP 正文?

发布于 2025-01-04 13:04:15 字数 474 浏览 1 评论 0原文

我想发送分块的 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请求的主体是transferrd分块的, 但是我用Wireshark捕获网络包,HTTP请求的主体没有分块传输。

如何通过Python中的http.client lib传输分块主体?

I want to send chunked HTTP body to test my own HTTP server.
So I wrote this python code:

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)

I expect the HTTP request's body is transferrd chunked,
but I capture the network package with Wireshark, the HTTP request's body is not transferred chunked.

How to transfer chunked body by http.client lib in python?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情绪失控 2025-01-11 13:04:15

好的,我明白了。

首先,编写我自己的分块编码函数。

然后使用 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()

OK, I get it.

First, write my own chunked encode function.

Then use putrequest(), putheader(), endheaders() and send() instead of 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()
等待圉鍢 2025-01-11 13:04:15

我建议,如果您已经知道数据的大小(如答案中所示),您只需设置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()

I'd suggest that if you already know the size of your data like in the answer given you could just set the Content-Length and send it all back in one hit, which is kind of what you're doing with the single call to conn.send anyway.

Chunked transfer encoding is most useful when you don't know how big the data is e.g. dynamically generated content. I've modified your code to illustrate:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文