FastAPI如何为OpenAPI(Swagger)文档请求头的Content-Type添加charset字符集
你之前的写法不生效是因为Form参数的media_type属性仅用于文件上传类的表单字段配置,无法修改全局的请求媒体类型声明,也不会改变解码逻辑。可以通过以下两种方案实现需求:
方案1:全局生效(所有表单接口都用cp932解码)
适合全站表单都使用cp932编码的场景,修改成本低
- 修改默认表单解码编码
FastAPI底层依赖Starlette处理表单解析,直接修改其默认编码即可全局生效:
from fastapi import FastAPI, Form from starlette.formparsers import URLEncodedFormParser # 全局设置表单解析默认编码为cp932 URLEncodedFormParser.default_encoding = "cp932" app = FastAPI()
- 自定义OpenAPI请求媒体类型
给对应路由添加openapi_extra参数,声明带charset的Content-Type,这样/docs页面就会显示正确的媒体类型:
@app.post("/", openapi_extra={ "requestBody": { "content": { "application/x-www-form-urlencoded; charset=cp932": { "schema": { "type": "object", "properties": {"username": {"type": "string"}}, "required": ["username"] } } } } } ) def post_hello(username: str = Form(...)): return {"Hello": "World!", "userName": username}
方案2:仅单个接口生效
适合只有部分接口需要使用cp932编码的场景,不影响其他接口逻辑
from fastapi import FastAPI, Depends, Request from typing import Annotated app = FastAPI() # 自定义cp932编码表单解析依赖 async def parse_cp932_form(request: Request) -> dict: raw_body = await request.body() decoded = raw_body.decode("cp932") form = {} for item in decoded.split("&"): if "=" in item: k, v = item.split("=", 1) form[k] = v return form @app.post("/", openapi_extra={ "requestBody": { "content": { "application/x-www-form-urlencoded; charset=cp932": { "schema": { "type": "object", "properties": {"username": {"type": "string"}}, "required": ["username"] } } } } } ) def post_hello(form_data: Annotated[dict, Depends(parse_cp932_form)]): username = form_data.get("username") return {"Hello": "World!", "userName": username}
两种方案都可以同时满足两个需求:OpenAPI文档显示带charset的Content-Type,参数自动按cp932解码。
内容的提问来源于stack exchange,提问作者Alumuko
相关产品推荐
相关产品推荐

