hello 大家好我是Monday,今天给大家带来一篇FastAPI中自定义中间件的文章。
一、前言:
1、什么中间件:
- 就是一个函数,它在被任何特定路径操作处理之前处理每个请求,且在每个 response 返回之前被调用
- 类似钩子函数
2、执行顺序
中间件会接收应用程序中的每个请求 Request
针对请求 Request 或其他功能,可以自定义代码块
再将请求 Request 传回路径操作函数,由应用程序的其余部分继续处理该请求
路径操作函数处理完后,中间件会获取到应用程序生成的响应 Response
中间件可以针对响应 Response 或其他功能,又可以自定义代码块
最后返回响应 Response 给客户端
3、中间件主要作用**:其实就是在请求前和请求后处理机制。通常我们的可以在中间件里处理的事情有:
二、中间件操作示例:
1、如官网提供的最简自定义的中间件示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import time import uvicorn from fastapi import FastAPI, Request, Response
app = FastAPI()
@app.middleware("http") async def log_request(request, call_next): print('请求开始前我可以处理事情1') response = await call_next(request)
print('请求开始后我可以处理的事情3')
return response
@app.get("/") async def not_timed(): print('请求开始后我可以处理的事情2') return {"message": "你好"}
if __name__ == '__main__': uvicorn.run('eg1:app', host="127.0.0.1", port=8000, debug=True, reload=True)
|
运行访问127.0.0.1:8000,看下控制台输出:
1 2 3 4 5
| INFO: Application startup complete. 请求开始前我可以处理事情1 请求开始后我可以处理的事情2 请求开始后我可以处理的事情3 INFO: 127.0.0.1:64807 - "GET / HTTP/1.1" 200 OK
|
我们还可以对返回的response进行处理,实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import time import uvicorn from fastapi import FastAPI, Request, Response
app = FastAPI()
@app.middleware("http") async def log_request(request, call_next): print('请求开始前我可以处理事情1') start_time = time.time() response = await call_next(request)
print('请求开始后我可以处理的事情3') process_time = time.time() - start_time response.headers["X-Process-Time"] = str(process_time) return response
@app.get("/") async def not_timed(response: Response): print('请求开始后我可以处理的事情2') return {"message": "你好"}
if __name__ == '__main__': uvicorn.run('eg2:app', host="127.0.0.1", port=8000, debug=True, reload=True)
|
我们可以看到,请求后的header 会出现X-Process-Time字段
2:基于BaseHTTPMiddleware的实现的中间件
多自定义中间件示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import uvicorn import time from fastapi import FastAPI, Request, Response from starlette.middleware.base import BaseHTTPMiddleware
app = FastAPI()
@app.middleware("http") async def log_request(request, call_next): print('请求开始前我可以处理事情1') response = await call_next(request)
print('请求开始后我可以处理的事情3')
return response
class CostimeHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next): print('请求开始前我可以处理事情4---CostimeHeaderMiddleware') start_time = time.time() responser = await call_next(request) process_time = round(time.time() - start_time, 4) responser.headers["X-Process-Time"] = f"{process_time} (s)" print('请求开始后我可以处理事情5----CostimeHeaderMiddleware') return responser
class CostimeHeaderMiddleware2(BaseHTTPMiddleware):
async def dispatch(self, request, call_next): print('请求开始前我可以处理事情6-----CostimeHeaderMiddleware2') start_time = time.time() responser = await call_next(request) process_time = round(time.time() - start_time, 4) responser.headers["X-Process-Time"] = f"{process_time} (s)" print('请求开始后我可以处理事情7---CostimeHeaderMiddleware2') return responser
app.add_middleware(CostimeHeaderMiddleware) app.add_middleware(CostimeHeaderMiddleware2)
@app.get("/") async def not_timed(): print('请求开始后我可以处理的事情2') return {"message": "你好"}
if __name__ == '__main__': uvicorn.run('eg3:app', host="127.0.0.1", port=8000, debug=True, reload=True)
|
运行结果:
1 2 3 4 5 6 7 8
| 请求开始前我可以处理事情6-----CostimeHeaderMiddleware2 请求开始前我可以处理事情4---CostimeHeaderMiddleware 请求开始前我可以处理事情1 请求开始后我可以处理的事情2 请求开始后我可以处理的事情3 请求开始后我可以处理事情5----CostimeHeaderMiddleware 请求开始后我可以处理事情7---CostimeHeaderMiddleware2 INFO: 127.0.0.1:50065 - "GET / HTTP/1.1" 200 OK
|
结论:
(1)从上面的输出结果可以看得到我们的中间件的注册顺序非常的重要。他们的上面的注册顺序是:
注册显示:
1 2
| app.add_middleware(CostimeHeaderMiddleware) app.add_middleware(CostimeHeaderMiddleware2)
|
结果显示:
请求开始前我可以处理事情6——-CostimeHeaderMiddleware2
请求开始前我可以处理事情4—-CostimeHeaderMiddleware
——>越是最晚注册的,越最先执行,同时也是最后收尾执行的
(2)假如你有需要使用中间件来处理全局异常的捕获的话,放在最外层去处理!
3:中间件中获取最终responser返回值
下面这篇文章做出了解释
Fastapi框架-冷饭再炒-基础知识补充篇(5)- 自定义中间件,在中间获取响应体报文 - 掘金 (juejin.cn)
参考链接:
链接1:https://juejin.cn/post/6971451349141553165
链接2:中间件 - FastAPI (tiangolo.com)
结束语:
今天的分享就到这里了,欢迎大家关注微信公众号”菜鸟童靴“