如何使用Python HTTPX库发送等价于有效CURL请求的multipart/form-data POST请求至OpenGear REST API
如何使用Python HTTPX库发送等价于有效CURL请求的multipart/form-data POST请求至OpenGear REST API
我明白你遇到的问题了——你有一个能正常工作的curl命令,但用HTTPX尝试了几种POST方式都没成功,从Nginx日志来看,请求格式明显不对。咱们来一步步解决这个问题:
问题根源分析
你的curl命令用-F参数发送的是multipart/form-data格式的表单数据,curl会自动处理这个格式的核心细节:比如生成用于分隔字段的边界标识符(boundary)、自动设置带boundary的Content-Type头。但你的HTTPX代码犯了两个关键错误:
- 手动设置Content-Type头:当你硬指定
multipart/form-data时,HTTPX无法自动添加必要的boundary参数,服务器缺少这个标识就无法正确解析multipart数据。 - 用错参数传递数据:你用
data参数传递字段,但默认情况下HTTPX会把data编码成application/x-www-form-urlencoded格式,哪怕你改了Content-Type头,也不会生成符合要求的multipart结构。
正确的HTTPX实现代码
正确的做法是让HTTPX自动处理multipart格式的所有细节,不需要手动设置Content-Type头,而是用files参数来传递curl里用-F定义的字段(哪怕这些字段不是实际文件,HTTPX也会把它们当作multipart表单的普通字段处理):
# 假设你已经初始化好带会话的api_client对象 form_fields = { # 元组格式:(文件名, 字段值),非文件字段文件名设为None即可 "firmware_url": (None, "https://example.com/path/to/file/file.name"), "firmware_options": (None, "-R") } # 发送请求,无需手动设置Content-Type response = api_client.post( f"https://{SERVER}/api/v2/system/firmware_upgrade", files=form_fields ) # 验证请求结果 print(f"响应状态码: {response.status_code}") print(f"响应内容: {response.text}")
额外说明
如果你的api_client会话没有预先包含Authorization Token,记得在请求中添加对应的头:
headers = {"Authorization": f"Token {TOKEN}"} response = api_client.post( f"https://{SERVER}/api/v2/system/firmware_upgrade", files=form_fields, headers=headers )
为什么之前的尝试失败?
从你提供的Nginx日志就能看出问题:
- 使用raw data dict时,HTTPX把数据编码成了urlencoded格式,但你手动设置了multipart的Content-Type,服务器拿到格式不匹配的数据,直接返回400错误,甚至出现了把请求体误当作单独URL请求的异常情况。
- JSON dumps的方式完全不符合服务器期望的multipart表单格式,自然无法被正确解析。
备注:内容来源于stack exchange,提问作者krizzo
相关产品推荐
相关产品推荐

