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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:05:21