Skip to content

中间件与异常处理

中间件、异常处理器、CORS、GZip。

Updated View as Markdown
For humans

中间件与异常处理

中间件管横切逻辑(日志、CORS、压缩),异常处理器管错误出口。面试主线:中间件怎么写、异常怎么统一处理。

中间件

@app.middleware("http")
async def timing_middleware(request: Request, call_next):
    start = time.perf_counter()
    response = await call_next(request)     # 进入内层
    response.headers["X-Process-Time"] = str(time.perf_counter() - start)
    return response
  • 洋葱模型:请求逐层进入,响应逐层返回(详见设计模式篇)
  • call_next 是进入下一层的开关,不调用就拦截请求
  • 注册顺序决定执行顺序,先注册的在外层
  • 横切所有请求的逻辑(日志、限流、统一响应头)放中间件

异常处理器

from fastapi import HTTPException, Request
from fastapi.responses import JSONResponse

class BizError(Exception):
    def __init__(self, code: int, message: str):
        self.code, self.message = code, message

@app.exception_handler(BizError)
async def biz_error_handler(request: Request, exc: BizError):
    return JSONResponse(status_code=400,
                        content={"code": exc.code, "message": exc.message})
异常类型 处理
HTTPException 内置,raise HTTPException(404, "用户不存在")
自定义业务异常 @app.exception_handler(MyError) 统一出口
未知异常 兜底 handler(500,记日志防泄漏细节)

工程模式:业务代码抛自定义异常(BizError),异常处理器统一转 JSON 响应。错误码、错误消息、日志在处理器里集中管理,路由函数不写 try/except。

CORS

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://front.example.com"],   # 精确域名, 别用 *
    allow_methods=["*"],
    allow_headers=["*"],
)

前后端分离必配:浏览器跨域请求先发 OPTIONS 预检,中间件响应 CORS 头。生产 allow_origins 要精确配置,*allow_credentials=True 会失效(浏览器规范)。

GZip 与静态资源

from starlette.middleware.gzip import GZipMiddleware
app.add_middleware(GZipMiddleware, minimum_size=1000)   # 响应压缩
  • GZip:大响应压缩,节省带宽,CPU 换带宽
  • StaticFiles:静态资源挂载(前端构建产物)
  • 中间件顺序:CORS 在最外层,压缩在内层

面试追问

  1. 中间件怎么写? @app.middleware(“http”),call_next 进入内层,响应返回再加工。不调 call_next 即拦截
  2. HTTPException 和自定义异常? HTTPException 内置快捷抛错;自定义异常配 exception_handler 统一转 JSON,业务代码不写 try/except
  3. CORS 怎么配? CORSMiddleware,allow_origins 精确配置。预检请求 OPTIONS 由中间件处理
  4. 异常处理器的优先级? 先匹配具体异常类型,再匹配父类,再兜底 Exception
  5. 中间件和依赖的执行顺序? 中间件先于路由和依赖执行(外层)。全局横切用中间件,接口逻辑用依赖
Navigation

Type to search…

↑↓ navigate↵ selectEsc close