一、前言
FastAPI 的高级用法可以为开发人员带来许多好处。它能帮助实现更复杂的路由逻辑和参数处理,使应用程序能够处理各种不同的请求场景,提高应用程序的灵活性和可扩展性。
在数据验证和转换方面,高级用法提供了更精细和准确的控制,确保输入数据的质量和安全性。它还能更高效地处理异步操作,提升应用程序的性能和响应速度,特别是在处理大量并发请求时优势明显。
此外,高级用法还有助于更好地整合数据库操作、实现数据的持久化和查询优化,以及实现更严格的认证和授权机制,保护应用程序的敏感数据和功能。总之,掌握 FastAPI 的高级用法可以帮助开发人员构建出功能更强大、性能更卓越、安全可靠的 Web 应用程序。
本篇学习FastAPI中高级中间件的相关内容,包括添加ASGI中间件、集成的中间件以及一些具体中间件的用法。
二、术语
2.1. middleware函数
middleware函数(中间件)它在每个请求被特定的路径操作处理之前,以及在每个响应返回之前工作。可以用于实现多种通用功能,例如身份验证、日志记录、错误处理、请求处理、缓存等。其主要作用是在请求和响应的处理过程中添加额外的处理逻辑,而无需在每个具体的路由处理函数中重复编写这些逻辑。
一般在碰到以下需求场景时,可以考虑使用中间件来实现:
- 身份验证:验证请求的身份,如检查 JWT token 或使用 OAuth2 进行验证;
- 日志记录:记录请求和响应的日志,包括请求方法、URL、响应状态码等信息;
- 错误处理:处理应用程序中的异常情况,捕获异常并返回自定义的错误响应;
- 请求处理:对请求进行处理,例如解析请求参数、验证请求数据等;
- 缓存:在中间件中检查缓存中是否存在请求的响应,如果存在则直接返回缓存的响应。
2.2.HTTPSRedirectMiddleware
强制所有传入请求必须是https或wss,否则将会被重定向。
2.3.TrustedHostMiddleware
强制所有传入的请求都正确设置的host请求头。
2.4.GZipMiddleware
处理任何在请求头Accept-Encoding
中包含“gzip”的请求为GZip响应。
三、前置条件
3.1. 创建虚拟环境&安装依赖
增加Google Search以及langchainhub的依赖
conda create -n fastapi_test python=3.10
conda activate fastapi_test
pip install fastapi uvicorn
四、技术实现
4.1. 自定义中间件
# -*- coding: utf-8 -*-
import uvicorn
from fastapi import FastAPI, Request, HTTPException
from starlette import status
app = FastAPI()
black_list = ['192.168.102.88']
@app.middleware("http")
async def my_middleware(request: Request, call_next):
client_host = request.client.host
print(f"client_host: {client_host}")
if client_host in black_list:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Prohibit access"
)
else:
response = await call_next(request)
return response
@app.get("/items/")
async def read_items():
return [{"item_id": "Foo"}]
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0',port=7777)
调用结果:
正常访问,未命中黑名单:
非法访问,命中黑名单:
4.2. HTTPSRedirectMiddleware
强制所有传入请求必须是https或wss。
# -*- coding: utf-8 -*-
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
app = FastAPI()
app.add_middleware(HTTPSRedirectMiddleware)
@app.get("/hello")
async def main():
return {"message": "Hello World"}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=7777)
调用结果:
http请求会重定向至https请求
4.3. TrustedHostMiddleware
强制所有传入的请求都正确设置的主机请求头。
# -*- coding: utf-8 -*-
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.trustedhost import TrustedHostMiddleware
app = FastAPI()
app.add_middleware(
TrustedHostMiddleware, allowed_hosts=["localhost"]
)
@app.get("/hello")
async def main():
return {"message": "Hello World"}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=7777)
调用结果:
使用代码指定的域名:localhost > 正常访问
使用非代码指定的域名:127.0.0.1 > 禁止访问,提示:Invalid host header
4.4. GZipMiddleware
处理 Accept-Encoding 标头中包含“gzip”的任何请求,小于minimum_size(默认值是500)将不会执行GZip响应。
# -*- coding: utf-8 -*-
import uvicorn
from fastapi import FastAPI
from starlette.middleware.gzip import GZipMiddleware
app = FastAPI()
app.add_middleware(GZipMiddleware, minimum_size=1)
@app.get("/hello")
async def main():
return {"message": "Hello World"}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=7777)
将minimum_size设置成100