FastAPI 提供了非常灵活和强大的工具,使我们能够在请求的生命周期中插入自定义处理逻辑。通过中间件、依赖注入和事件处理等机制,我们可以在请求的不同阶段执行自定义操作,例如日志记录、身份验证、权限检查、请求修改等。
本文将深入探讨 FastAPI 请求生命周期的各个阶段,并展示如何在这些阶段插入自定义处理逻辑。
1. 请求生命周期概述
在 FastAPI 中,HTTP 请求的生命周期大致可以分为以下几个阶段:
- 请求接收:请求到达服务器,FastAPI 启动并接受请求。
- 中间件处理:请求通过应用的中间件(如果有的话),可以在这里做一些如日志记录、身份验证、请求修改等操作。
- 路由处理:请求通过中间件后,FastAPI 根据请求路径和方法匹配到相应的路由函数,路由函数进行业务处理。
- 响应生成:路由函数返回响应,FastAPI 将生成的响应返回给客户端。
- 中间件后处理:响应通过中间件处理后,可能会被修改(例如添加响应头)。
- 响应返回客户端:最终响应返回给客户端。
2. 如何在请求的不同阶段插入自定义处理逻辑
2.1 使用中间件插入自定义处理逻辑
中间件是在请求生命周期的较早阶段进行处理的最佳方式。它允许我们在请求到达路由处理函数之前对请求进行处理,也可以在响应返回客户端之前对响应进行修改。
2.1.1 创建自定义中间件
通过继承 BaseHTTPMiddleware
类,我们可以创建自定义的中间件。在 dispatch
方法中,可以处理请求和响应:
from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
import logging
app = FastAPI()
# 创建自定义中间件
class LoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
# 请求接收时的日志记录
logging.info(f"Request: {request.method} {request.url}")
# 请求处理
response = await call_next(request)
# 响应生成时的日志记录
logging.info(f"Response: {response.status_code}")
return response
# 注册中间件
app.add_middleware(LoggingMiddleware)
@app.get("/items/{item_id}")
async def get_item(item_id: int):
return {"item_id": item_id}
代码解析:
- 请求处理:在
dispatch
方法中,日志记录请求的 HTTP 方法和 URL。 - 响应处理:在响应返回客户端之前,我们也可以记录响应的状态码。
- 中间件注册:通过
app.add_middleware
注册自定义的LoggingMiddleware
。
2.2 使用依赖注入处理请求中的逻辑
FastAPI 的依赖注入系统允许我们在请求生命周期的各个阶段插入自定义的处理逻辑,例如身份验证、权限检查、请求参数验证等。
2.2.1 依赖注入示例:身份验证
我们可以在请求处理之前插入身份验证逻辑,确保只有通过身份验证的请求才能访问某些 API。
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from typing import List
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# 模拟用户认证的依赖
def get_current_user(token: str = Depends(oauth2_scheme)):
if token != "valid-token":
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
return {"username": "john"}
@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
return current_user
代码解析:
- 依赖注入:
get_current_user
函数是一个依赖,它使用Depends
注入到请求中。这个依赖验证Authorization
头中的 OAuth2 令牌。 - 身份验证:如果令牌不匹配
"valid-token"
,则会抛出HTTPException
,返回 401 错误。 - 保护路由:
/users/me
路由会通过Depends
注入get_current_user
来执行身份验证。
2.2.2 依赖注入示例:日志记录
我们还可以在请求处理过程中使用依赖注入来记录日志。
from fastapi import FastAPI, Depends
import logging
app = FastAPI()
# 日志记录的依赖
def log_request(request: str):
logging.info(f"Request received: {request}")
@app.get("/items/{item_id}")
async def get_item(item_id: int, request: str = Depends(log_request)):
return {"item_id": item_id}
代码解析:
- 日志记录依赖:
log_request
函数会在每个请求到达时记录日志。 - 依赖注入:
request
参数通过Depends(log_request)
注入,每次访问/items/{item_id}
路由时,都会执行log_request
函数来记录日志。
2.3 使用事件处理插入自定义处理逻辑
FastAPI 提供了事件处理机制,可以在请求生命周期的特定时机触发某些操作。例如,我们可以在应用启动时加载数据库连接,或在应用关闭时释放资源。
2.3.1 事件处理示例:应用启动和关闭时的处理
from fastapi import FastAPI
import logging
app = FastAPI()
@app.on_event("startup")
async def startup_event():
# 应用启动时执行的逻辑
logging.info("Application has started")
@app.on_event("shutdown")
async def shutdown_event():
# 应用关闭时执行的逻辑
logging.info("Application is shutting down")
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
代码解析:
@app.on_event("startup")
:在应用启动时执行一些逻辑(如日志记录、资源初始化)。@app.on_event("shutdown")
:在应用关闭时执行清理操作(如关闭数据库连接、释放资源)。
2.4 中间件与依赖注入的结合使用
中间件和依赖注入可以结合使用,在不同的生命周期阶段执行不同的操作。例如,可以使用中间件处理全局的日志记录、CORS 或身份验证,而使用依赖注入处理每个请求的业务逻辑,如输入验证、权限验证等。
from fastapi import FastAPI, Depends, HTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
app = FastAPI()
# 自定义中间件:记录请求和响应
class LoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
logging.info(f"Request: {request.method} {request.url}")
response = await call_next(request)
logging.info(f"Response: {response.status_code}")
return response
app.add_middleware(LoggingMiddleware)
# 身份验证的依赖
def verify_token(token: str = Depends()):
if token != "valid-token":
raise HTTPException(status_code=401, detail="Invalid credentials")
@app.get("/secure-data")
async def get_secure_data(token: str = Depends(verify_token)):
return {"data": "Secure Data"}
代码解析:
- 中间件:
LoggingMiddleware
在请求和响应阶段记录日志。 - 依赖注入:
verify_token
验证请求中的认证信息,确保只有有效的令牌才能访问/secure-data
路由。
FastAPI 提供了灵活的工具和机制,让我们可以在请求生命周期的各个阶段插入自定义处理逻辑。具体来说,我们可以通过以下方式在请求的不同阶段插入自定义逻辑:
- 中间件:在请求和响应生命周期的早期和后期进行处理,例如日志记录、CORS、身份验证等。
- 依赖注入:在路由函数处理请求之前,执行如身份验证、权限检查、参数验证等任务。
- 事件处理:在应用启动和关闭时插入自定义操作。
这些机制使得 FastAPI 可以灵活地处理不同的请求场景,从而帮助我们构建高效、可维护的 Web 应用。
更多请关注公众号 “学GIS的小宝同学”