FastAPI 高级技巧:自定义 Request 和 APIRoute 类
前言
在 FastAPI 开发中,我们有时需要对请求处理流程进行深度定制。本文将深入探讨如何通过自定义 Request
和 APIRoute
类来实现高级请求处理功能,这是 FastAPI 提供的一项强大但较少被提及的特性。
适用场景
自定义请求和路由类特别适合以下场景:
- 特殊编码处理:如处理 MessagePack 等非 JSON 格式的请求体
- 数据预处理:自动解压 gzip 压缩的请求体
- 请求监控:记录所有请求的原始数据
- 性能监控:测量请求处理时间并添加到响应头
核心概念解析
Request 类
Request
类是 FastAPI 处理 HTTP 请求的核心组件,它封装了请求的所有信息,包括头部、正文和元数据。
APIRoute 类
APIRoute
负责将请求路由到对应的路径操作函数,并处理响应生成过程。
实战示例:Gzip 请求处理
创建自定义 GzipRequest
from fastapi import Request
import gzip
class GzipRequest(Request):
async def body(self) -> bytes:
if not hasattr(self, "_body"):
body = await super().body()
if "gzip" in self.headers.get("Content-Encoding", ""):
body = gzip.decompress(body)
self._body = body
return self._body
这个自定义类重写了 body()
方法,自动检测并解压 gzip 编码的请求体。
创建自定义 GzipRoute
from fastapi.routing import APIRoute
class GzipRoute(APIRoute):
def get_route_handler(self):
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request):
request = GzipRequest(request.scope, request.receive)
return await original_route_handler(request)
return custom_route_handler
这个路由类确保所有传入请求都被包装为我们的 GzipRequest
实例。
高级应用:异常处理中的请求访问
有时我们需要在异常处理中访问原始请求体:
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
@app.post("/")
async def process(request: Request):
try:
return await request.json()
except Exception:
body = await request.body()
print(f"Error processing: {body}")
raise HTTPException(status_code=400)
路由级别的自定义
我们还可以为特定路由应用自定义路由类:
from fastapi import APIRouter, Response
import time
class TimedRoute(APIRoute):
def get_route_handler(self):
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request):
start_time = time.time()
response = await original_route_handler(request)
process_time = time.time() - start_time
response.headers["X-Response-Time"] = str(process_time)
return response
return custom_route_handler
router = APIRouter(route_class=TimedRoute)
这个实现会为所有该路由下的请求添加响应时间头信息。
技术细节说明
- ASGI 规范:
Request
依赖于 ASGI 的scope
字典和receive
函数 - 性能考虑:自定义处理会增加少量开销,应谨慎使用
- 中间件对比:相比中间件,自定义路由类提供了更细粒度的控制
最佳实践建议
- 优先考虑使用中间件解决通用问题
- 仅在需要特定路由特殊处理时使用自定义路由类
- 注意异常处理中的资源清理
- 为复杂逻辑添加充分的文档说明
总结
通过自定义 Request
和 APIRoute
类,开发者可以深入 FastAPI 的请求处理流程,实现高度定制化的功能。这种技术虽然强大,但应谨慎使用,确保不会破坏框架的核心约定和性能特性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考