You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用FastAPI解析SendGrid的原始multipart/form-data Webhook?

如何用FastAPI解析SendGrid入站Webhook的原始multipart/form-data数据

我想用FastAPI接收SendGrid的入站解析Webhook,该Webhook以原始multipart/form-data格式传递数据。我的代码能接收到负载,但解析时会出现422 Unprocessable Entity错误(Pydantic验证失败)。

请问是否可以直接通过FastAPI解析这类数据?如果需要手动解析再转换格式传入FastAPI,希望提供示例代码。


最小可复现示例

FastAPI接收代码

from typing import Any
from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/inbound_email")
async def inbound_email(
    headers: Any = Form(...),
    subject: Any = Form(...),
    ):
    try:
        print(headers)
        print(subject)
    except Exception as e:
        print(f"inbound_email exception: {e}")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("min_reproducible_example:app", host="127.0.0.1", port=54200, reload=True)

模拟SendGrid Webhook的curl测试命令

curl --location 'https://myurlhere.ngrok-free.app/inbound_email' \
--data '--xYzZY
Content-Disposition: form-data; name="headers"

Content-Type: multipart/alternative; boundary="00000000000021b9ea0605bbd8ac"

--xYzZY
Content-Disposition: form-data; name="subject"

Inbound test 5
--xYzZY--
'

错误输出

应用日志:

"POST /inbound_email HTTP/1.1" 422 Unprocessable Entity

Postman返回的详细错误:

{
    "detail": [
        {
            "type": "missing",
            "loc": [
                "body",
                "headers"
            ],
            "msg": "Field required",
            "input": null
        }
    ]
}

尝试直接解析Request的代码及结果

from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/inbound_email")
async def inbound_email(
    request: Request,
    ):
    try:
        raw_body = await request.body()
        print(raw_body.decode("utf-8"))
        form_data = await request.form()
        body_headers = form_data.get("headers")
        subject = form_data.get("subject")
        print("body_headers:", body_headers)
        print("subject:", subject)
    except Exception as e:
        print(f"inbound_email exception: {e}")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("min_reproducible_example:app", host="127.0.0.1", port=54200, reload=True)

终端输出:

--xYzZY
Content-Disposition: form-data; name="headers"

Content-Type: multipart/alternative; boundary="00000000000021b9ea0605bbd8ac"

--xYzZY
Content-Disposition: form-data; name="subject"

Inbound test 5
--xYzZY--

body_headers: None
subject: None

补充说明

  • 通过Postman发送请求时,以raw格式传递正文文本,使用默认请求头,也曾尝试显式指定格式、边界符等请求头,均无效。
  • 其他格式(包括Postman的form-data)的POST请求能正常被FastAPI解析,仅这种原始文本格式的multipart/form-data无法解析。

内容的提问来源于stack exchange,提问作者FlightPlan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:10:19