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

如何让所有异常都经过FastAPI中间件处理?

问题

使用FastAPI开发应用时,希望通过统一的中间件(按异常类型用不同except块)处理所有抛出的异常,尝试编写了如下中间件:

from fastapi import APIRouter, FastAPI, Request, HTTPException, Response, status
from starlette.middleware.base import BaseHTTPMiddleware
from fastapi.responses import JSONResponse

class ExceptionHandlerMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        try:
            return await call_next(request)
        except HTTPException as e:
            return JSONResponse(status_code=e.status_code, content={'message': e.detail})
        except Exception as e:
            return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={'message': str(e)})

# app creation and config go here....

app.add_middleware(ExceptionHandlerMiddleware)

但问题在于,HTTPException这类被FastAPI默认处理的异常,会在到达中间件前就被默认处理器拦截,无法进入中间件的except块。FastAPI文档提供的重写特定异常默认行为的方式繁琐且扩展性差,希望找到无需装饰器、全局强制所有异常都经过中间件处理的方法。

解决方案

要让所有异常都流经你的中间件,核心是移除FastAPI默认注册的异常处理器,这样异常就不会被提前拦截,而是传递到中间件的try/except块中。

步骤1:移除默认异常处理器

FastAPI默认会为HTTPException和RequestValidationError(对应422参数验证错误)注册专属处理器,需要先把它们从应用的异常处理器字典中移除:

from fastapi import RequestValidationError

# 创建应用实例
app = FastAPI()

# 移除默认的HTTPException处理器
app.exception_handlers.pop(HTTPException)
# 移除默认的RequestValidationError处理器(处理422错误)
app.exception_handlers.pop(RequestValidationError)

步骤2:保留中间件并调整异常捕获逻辑

此时你的中间件就能捕获到所有异常,包括原来被默认处理的HTTPException和参数验证异常。如果需要统一处理RequestValidationError,可以在中间件中新增对应的except块:

class ExceptionHandlerMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        try:
            return await call_next(request)
        except HTTPException as e:
            return JSONResponse(status_code=e.status_code, content={'message': e.detail})
        except RequestValidationError as e:
            # 自定义参数验证错误的返回格式
            error_details = [{'loc': err['loc'], 'msg': err['msg'], 'type': err['type']} for err in e.errors()]
            return JSONResponse(
                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                content={'message': '参数验证失败', 'errors': error_details}
            )
        except Exception as e:
            return JSONResponse(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                content={'message': '服务器内部错误', 'detail': str(e)}
            )

# 添加中间件
app.add_middleware(ExceptionHandlerMiddleware)

关键说明

  • 移除默认处理器后,所有未被捕获的异常都会传递到中间件的try/except流程中,完全由你统一控制返回格式。
  • 这种方式无需使用任何装饰器,仅通过修改应用配置和中间件即可实现全局异常统一处理。
  • 若需要处理其他自定义异常,只需在中间件中新增对应的except块即可,扩展性强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:49:56