FastAPI:如何在OpenAPI中自定义验证错误并隐藏正则规则?
解决FastAPI Swagger提前暴露正则验证错误的方案
问题核心是Swagger UI会基于OpenAPI Schema里的pattern字段做前端预校验,这一步在请求到达后端之前就完成了,所以你写的自定义RequestValidationError处理器根本没机会触发。下面是三个可行的解决思路:
方案1:自定义字段验证,不把正则写入OpenAPI Schema
放弃Pydantic内置的StringConstraints(pattern=...),改用自定义字段验证器,这样正则逻辑只在后端执行,不会出现在OpenAPI文档里。
from pydantic import BaseModel, field_validator from typing import Annotated import re # 方式1:用自定义字段类 class ValidatedUsername(str): @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, v): if not isinstance(v, str): raise ValueError("必须是字符串类型") if not re.match(r'^[a-z0-9_]{5,15}$', v): # 你的正则逻辑 raise ValueError("用户名格式不符合要求") return v # 方式2:用Annotated结合字段验证器 def validate_password(v: str) -> str: if not re.match(r'^(?=.*[A-Z])(?=.*\d).{8,}$', v): raise ValueError("密码强度不足") return v ValidatedPassword = Annotated[str, field_validator(validate_password)] # 模型使用自定义字段 class User(BaseModel): username: ValidatedUsername password: ValidatedPassword
这种方法最彻底,Swagger的Schema里不会出现任何正则相关内容,所有校验都由后端处理,自定义错误处理器能正常触发。
方案2:禁用Swagger的前端验证
直接修改Swagger UI的配置,关闭它的前端校验功能,让所有请求都直接发到后端,由你的自定义处理器处理错误。
from fastapi import FastAPI from fastapi.openapi.docs import get_swagger_ui_html app = FastAPI(docs_url=None) # 先关闭默认的docs路由 # 自定义Swagger UI路由,添加禁用验证的参数 @app.get("/docs", include_in_schema=False) async def custom_swagger_ui(): return get_swagger_ui_html( openapi_url=app.openapi_url, title="API文档", swagger_ui_parameters={"validatorUrl": None} # 关键:禁用前端验证器 )
这个方法最简单,不用改现有模型和验证逻辑,只要修改Swagger的配置就行。缺点是如果你的Schema里本来就有pattern,用户还是能在Swagger的字段描述里看到正则,只是不会提前校验。
方案3:修改OpenAPI Schema,移除所有pattern字段
如果已经大量使用了StringConstraints(pattern=...),不想逐个修改模型,可以在应用启动时自动遍历OpenAPI Schema,把所有pattern属性删掉。
from fastapi import FastAPI from pydantic import BaseModel, StringConstraints app = FastAPI() # 现有模型示例 class Item(BaseModel): code: str = StringConstraints(pattern=r'^PROD-\d{4}$') name: str = StringConstraints(pattern=r'^[A-Za-z ]{3,20}$') @app.post("/items") async def create_item(item: Item): return {"item": item} # 递归移除Schema中的pattern字段 def clean_patterns(schema): if isinstance(schema, dict): schema.pop("pattern", None) for value in schema.values(): clean_patterns(value) elif isinstance(schema, list): for item in schema: clean_patterns(item) # 启动时修改OpenAPI Schema @app.on_event("startup") async def modify_openapi(): clean_patterns(app.openapi_schema)
这样生成的Swagger文档里不会显示任何正则,同时前端也不会做预校验,请求会正常到达后端触发自定义错误处理器。
内容的提问来源于stack exchange,提问作者Shahjalal Shohag
相关产品推荐
相关产品推荐

