中间件与依赖系统:构建高效 Web 后端的双重利器

文章目录

  • [一、 中间件(Middleware):全局的"拦截器"](#一、 中间件(Middleware):全局的“拦截器”)
    • [1.1 核心概念](#1.1 核心概念)
    • [1.2 执行原理](#1.2 执行原理)
    • [1.3 代码实现](#1.3 代码实现)
    • [1.4 多中间件执行顺序](#1.4 多中间件执行顺序)
  • [二、 依赖系统(Dependency Injection):精细化的"业务注入"](#二、 依赖系统(Dependency Injection):精细化的“业务注入”)
    • [2.1 为什么要用依赖系统?](#2.1 为什么要用依赖系统?)
    • [2.2 如何实现依赖?](#2.2 如何实现依赖?)
  • 三、如何实现"局部中间件"?
  • [四、 注意注意注意注意注意](#四、 注意注意注意注意注意)

一、 中间件(Middleware):全局的"拦截器"

1.1 核心概念

中间件是一个在每个 请求 (Request) 被处理之前,以及每个 响应 (Response) 返回之前运行的函数。它是全局性的,一旦建立,项目中的所有路由都会经过它。

1.2 执行原理

中间件通过 call_next 建立起请求的传递链:

1、前置处理:请求向下传递(交给路由)之前执行。

2、传递请求:调用 await call_next(request)

3、后置处理:路由处理完后,在响应返回给客户端之前执行。

1.3 代码实现

main.py 中直接定义(注意:APIRouter 不支持直接定义中间件):

python 复制代码
@app.middleware("http")
async def process_timer(request: Request, call_next):
    # 【前置】记录请求开始时间
    print("中间件:开始拦截请求")
    
    response = await call_next(request)
    
    # 【后置】添加自定义响应头或日志
    print("中间件:准备返回结果")
    return response

1.4 多中间件执行顺序

当有多个中间件时,执行顺序是从下向上(或者说后定义的先执行请求,先定义的后处理响应)。

二、 依赖系统(Dependency Injection):精细化的"业务注入"

2.1 为什么要用依赖系统?

如果说中间件是"强迫所有人过安检",那么依赖系统就是"谁需要谁申请"。

假设你写了两个接口:一个是"查看个人资料",一个是"修改个人资料"。这两个接口都需要先验证用户是否登录。

这时候,你写一个验证函数作为"依赖项",谁需要验证,谁就在参数里"领取"它。

2.2 如何实现依赖?

python 复制代码
# 1. 定义一个依赖项
async def verify_token(token: str):
    if token != "secret-key":
        return {"error": "暗号不对,不准入内"}
    return "验证通过"

# 2. 在需要的路由里"领取"它
@user_router.get("/info/")
async def get_user_info(auth_status = Depends(verify_token)):
    # 只有 verify_token 成功了,才会执行这里
    return {"status": auth_status, "name": "Chang Yang"}

三、如何实现"局部中间件"?

中间件一旦建立,所有路由都得走,能不能让某些路由走,某些不走?
答案是:当然能!!!

在 FastAPI 里,这通常有两种实现方案:

  • Plan A:在中间件内部做排除(白名单)
    在中间件函数里加个判断:
python 复制代码
@app.middleware("http")
async def selective_middleware(request: Request, call_next):
    # 定义不需要走中间件的路径
    white_list = ["/login", "/register", "/docs"]
    
    if request.url.path in white_list:
        return await call_next(request) # 直接放行,不走下面的逻辑
    
    # 下面是正常的拦截逻辑...
    print("正在拦截受保护的路径")
    return await call_next(request)
  • Plan B:使用"依赖注入"模拟局部中间件
    部分代码示例(这里是一个单独的py文件):
python 复制代码
import time
# 用依赖系统上实现局部中间件
# 第一步:定义一个依赖函数
async def my_timer_dep():
    start_time = time.time()
    yield
    process_time = time.time() - start_time
    print("接口耗时:", process_time, "秒")
python 复制代码
from fastapi import Depends
# 导入依赖函数
from aps.Common.deps import my_timer_dep
@api_router.get('/{id}',dependencies=[Depends(my_timer_dep)])
async def get_user(id: int):
    return {
        'id': id,
        'name': '张三'
    }

四、 注意注意注意注意注意

  • 路径斜杠问题:在定义带有查询参数的路径时,结尾建议加上 /。虽然某些 AI 或文档说不加也能跑,但在标准 RESTful 实践和 FastAPI 的某些配置下,加斜杠能避免不必要的重定向问题。
  • 异步避坑:如果你在中间件里处理文件或耗时 I/O,一定要记得使用 await,否则会阻塞整个异步循环。
相关推荐
金玉满堂@bj1 小时前
Go 语言能做什么?
开发语言·后端·golang
ooseabiscuit1 小时前
Laravel6.x新特性全解析
java·开发语言·后端·mysql·spring
枕星而眠1 小时前
一篇吃透 C++ 核心基础:初始化、引用、指针、内联、重载、右值引用
开发语言·数据结构·c++·后端·visual studio
Zephyr_01 小时前
python基础
python
Royzst1 小时前
一、集合概述(前置基础)
开发语言·windows·python
Season4501 小时前
C/C++的类型转换
c语言·开发语言·c++
平安的平安1 小时前
Python大模型Function Calling实战:让AI拥有工具使用能力
开发语言·人工智能·python
xyq20241 小时前
Vue.js 实例
开发语言
源码之家1 小时前
计算机毕业设计:Python中药材数据可视化与智能分析平台 Django框架 中药数据分析 医药数据分析数据分析 可视化 爬虫 (建议收藏)✅
python·深度学习·信息可视化·数据分析·django·课程设计