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

FastAPI如何解码非UTF-8请求体(ISO-8859-1编码)

FastAPI接收ISO-8859-1编码请求并绑定Pydantic模型的解决方法

FastAPI默认处理text/plain请求体时,不管Content-Type头里的charset参数,都会强制用UTF-8解码——这是因为底层Starlette框架的PlainTextRequestParser硬编码了UTF-8作为默认编码,不会从请求头里提取charset信息。下面给两个可行的解决方案:

方案一:自定义全局请求解析器(推荐)

直接替换Starlette默认的text/plain解析器,让它能从Content-Type头里读取charset并正确解码:

from fastapi import FastAPI
from starlette.requests import PlainTextRequestParser
import cgi
from pydantic import BaseModel

# 自定义解析器,支持从Content-Type提取charset
class CharsetAwarePlainTextParser(PlainTextRequestParser):
    async def parse(self):
        content_type = self.request.headers.get("content-type", "")
        _, options = cgi.parse_header(content_type)
        encoding = options.get("charset", "utf-8")
        body = await self.request.body()
        text = body.decode(encoding)
        # 按Starlette要求返回FormData格式,让FastAPI能绑定到Pydantic模型
        return self.form_data_class({"text": text})

app = FastAPI()
# 替换默认的text/plain解析器
app.router.request_parseors["text/plain"] = CharsetAwarePlainTextParser

# 定义Pydantic模型
class RequestModel(BaseModel):
    text: str

# 端点直接接收模型
@app.post("/process")
async def process_request(model: RequestModel):
    return {"decoded_content": model.text}

这个方案全局生效,所有接收text/plain的端点都会自动适配请求头里指定的编码,不用每个端点重复处理。

方案二:用依赖项处理单个端点

如果只是少数端点需要支持ISO-8859-1,不想修改全局配置,可以用依赖项单独处理解码:

from fastapi import FastAPI, Depends, Request
from pydantic import BaseModel
import cgi

app = FastAPI()

class RequestModel(BaseModel):
    text: str

# 定义依赖项,负责解码请求体
async def decode_request_body(request: Request) -> str:
    content_type = request.headers.get("content-type", "")
    _, options = cgi.parse_header(content_type)
    encoding = options.get("charset", "utf-8")
    body = await request.body()
    return body.decode(encoding)

# 端点通过依赖项获取解码后的文本,再绑定到模型
@app.post("/process")
async def process_request(decoded_text: str = Depends(decode_request_body)):
    model = RequestModel(text=decoded_text)
    return {"decoded_content": model.text}

这个方案更灵活,只对添加了该依赖项的端点生效,适合局部特殊场景。

补充说明

  • 两个方案都遵循HTTP规范:如果请求头没指定charset,会自动 fallback 到UTF-8解码。
  • 自定义解析器方案更适合全局需要支持多种编码的服务,依赖项方案适合单点特殊处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:20:09