Starlette 中间件深度解析:从基础到高级应用
什么是 Starlette 中间件?
Starlette 中间件是一种强大的机制,允许开发者在请求处理流程的不同阶段插入自定义逻辑。这些中间件遵循 ASGI 规范,不仅适用于 Starlette 应用,也能与任何兼容 ASGI 的框架协同工作。
中间件的基本使用
在 Starlette 中,中间件通过 middleware
参数配置,确保它们被异常处理器正确包裹:
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
from starlette.middleware.trustedhost import TrustedHostMiddleware
routes = [...]
middleware = [
Middleware(
TrustedHostMiddleware,
allowed_hosts=['example.com', '*.example.com'],
),
Middleware(HTTPSRedirectMiddleware)
]
app = Starlette(routes=routes, middleware=middleware)
默认中间件
每个 Starlette 应用默认包含两个中间件:
- ServerErrorMiddleware:最外层中间件,处理 500 错误和调试模式下的异常追踪
- ExceptionMiddleware:为特定异常类型关联处理函数
中间件执行顺序
中间件按照从上到下的顺序执行,执行流程如下:
ServerErrorMiddleware
↓
TrustedHostMiddleware
↓
HTTPSRedirectMiddleware
↓
ExceptionMiddleware
↓
路由系统
↓
端点处理
常用中间件详解
1. CORSMiddleware(跨域资源共享)
用于处理浏览器的跨域请求,通过添加适当的 CORS 头部实现。
from starlette.middleware.cors import CORSMiddleware
middleware = [
Middleware(
CORSMiddleware,
allow_origins=['https://example.com'],
allow_methods=['GET', 'POST'],
allow_headers=['X-Custom-Header']
)
]
重要参数:
allow_origins
:允许的源列表allow_methods
:允许的 HTTP 方法allow_headers
:允许的请求头max_age
:CORS 响应缓存时间
全局 CORS 处理建议
为确保所有响应(包括错误响应)都包含 CORS 头部,建议将整个应用包装在 CORSMiddleware 中:
app = Starlette()
app = CORSMiddleware(app=app, allow_origins=["*"])
2. SessionMiddleware(会话管理)
提供基于签名 cookie 的 HTTP 会话管理:
from starlette.middleware.sessions import SessionMiddleware
middleware = [
Middleware(
SessionMiddleware,
secret_key="your-secret-key",
https_only=True
)
]
关键特性:
- 数据可读但不可篡改
- 通过
request.session
字典接口访问 - 支持会话过期时间配置
3. HTTPSRedirectMiddleware(HTTPS 重定向)
强制所有请求使用 HTTPS 协议:
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
middleware = [
Middleware(HTTPSRedirectMiddleware)
]
4. TrustedHostMiddleware(可信主机验证)
防止 HTTP 主机头攻击:
from starlette.middleware.trustedhost import TrustedHostMiddleware
middleware = [
Middleware(
TrustedHostMiddleware,
allowed_hosts=['example.com', '*.example.com']
)
]
5. GZipMiddleware(GZip 压缩)
自动压缩响应内容:
from starlette.middleware.gzip import GZipMiddleware
middleware = [
Middleware(
GZipMiddleware,
minimum_size=1000,
compresslevel=6
)
]
注意事项:
- 默认不压缩小于 500 字节的响应
- 不会对已压缩内容进行二次压缩
自定义中间件开发
1. BaseHTTPMiddleware(基础 HTTP 中间件)
提供请求/响应接口的抽象类:
from starlette.middleware.base import BaseHTTPMiddleware
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
response.headers['X-Custom'] = 'Value'
return response
局限性:
- 会影响上下文变量的传播
- 不适用于需要精细控制 ASGI 消息的场景
2. 纯 ASGI 中间件
更底层的实现方式,完全遵循 ASGI 规范:
class PureASGIMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
if scope["type"] != "http":
return await self.app(scope, receive, send)
# 预处理逻辑
await self.app(scope, receive, send)
# 后处理逻辑
优势:
- 完全控制 ASGI 消息流
- 无 BaseHTTPMiddleware 的限制
- 更好的框架互操作性
中间件开发最佳实践
- 明确作用域:在中间件开头检查
scope["type"]
,确保只处理特定类型的请求 - 重用 Starlette 组件:利用
Request
、Headers
等高级抽象简化代码 - 保持无状态:避免在中间件实例中保存状态,应通过请求上下文传递数据
- 性能考虑:对于性能敏感的操作,考虑使用纯 ASGI 中间件
总结
Starlette 的中间件系统提供了从简单到复杂的多种实现方式,开发者可以根据需求选择合适的方法。无论是使用内置中间件快速实现常见功能,还是开发自定义中间件处理特定业务逻辑,Starlette 都提供了灵活而强大的工具集。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考