赞
踩
中间件可以理解为公用的函数。它作用在客户端和路径操作函数之间。
要创建中间件需要在函数的顶部使用装饰器@app.middleware(“http”)
#表示下面定义的函数是一个中间件,且app下的所有路径操作函数使用该中间件
@app.middleware("http")
#第一个参数必须是Request实例对象
#第二个参数表示一个回调函数
async def process_timer(req:Request,call_next):
start = time.time()
#call_next(req)表示将处理后的req转交给下一部分处理
#注意此处是一个异步!
response = await call_next(req)
timer = time.time() - start
response.headers["X-process-time"] = str(timer)
#返回处理后的响应
return response
注意多中间情况下顺序问题:
请求处理时: 先执行下方的中间件请求部分,后执行上方的中间件请求部分
响应处理时:先执行上方的中间件响应部分,后执行下方的中间件响应部分
出现这种顺序是由于fastapi中中间件修饰符的内部实现决定:
利用insert(0,object)的方式添加中间件,故下方的在前,上方的在后。
def add_middleware(
self, middleware_class: type, **options: typing.Any
) -> None: # pragma: no cover
self.user_middleware.insert(0, Middleware(middleware_class, **options))
self.middleware_stack = self.build_middleware_stack()
下面利用完整代码演示中间件的使用及顺序问题
from urllib import response
from fastapi import FastAPI,status,Request,Response
import time
app = FastAPI()
# 利用fastapi的middleware("http")装饰器表名下面的函数是一个中间件
# 表名该app下的路径操作函数都会受该中间件影响
@app.middleware("http")
# 中间件函数的形参必须有两个:
# 第一个为Request的实例对象,
# 第二个表示一个回调函数,并以Request实例对象作为输入
# 返回值必须为call_next的结果,或加工后的结果
async def process_timer(req:Request,call_next):
# 响应部分
start_time = time.time()
print("上方请求处理")
# call_next的调用表明其下方是响应部分
response = await call_next(req)
process_time = time.time() - start_time
response.headers["X-process-Time"] = str(process_time)
print("上方响应处理")
return response
@app.middleware("http")
async def process_token(req:Request,call_next):
token = req.headers.get("X-token")
if not token:
return Response(content="token not available",status_code=status.HTTP_401_UNAUTHORIZED)
print("下方请求处理")
res = await call_next(req)
print("下方响应处理")
return res
@app.get("/item/{item_id}")
async def read_item(item_id:int):
return {"item_id":item_id}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app="main:app",host="127.0.0.1",port=8080,reload=True)
执行结果满足上方的分析过程:
如果你使用了 yield 关键字依赖, 依赖中的退出代码将在执行中间件后执行.
如果有任何后台任务(稍后记录), 它们将在执行中间件后运行.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。