• fastapi_No.14_中间件


    中间件

    流程

    中间件可以理解为公用的函数。它作用在客户端和路径操作函数之间。

    1. 可以针对客户端的请求做一定处理后
    2. 再将结果返回给路径操作函数。(请求处理)
    3. 路径操作函数处理后,将响应交给中间件
    4. 中间件处理后将响应返回给客户端。(响应处理)
      在这里插入图片描述
      中间件由于既可以处理Request又可以处理Response,所以可以将中间件分成两个部分,一部分为请求处理部分,另外一个部分为响应处理部分。

    创建中间件

    要创建中间件需要在函数的顶部使用装饰器@app.middleware(“http”)

    • 第一步:使用中间件修饰器
    • 第二步:定义中间件函数
      • 两个形参:Request和回调函数
      • 回调函数上方的是请求处理部分
      • 回调函数下方的是响应处理部分
    #表示下面定义的函数是一个中间件,且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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    使用中间件

    注意多中间情况下顺序问题:
    请求处理时: 先执行下方的中间件请求部分,后执行上方的中间件请求部分
    响应处理时:先执行上方的中间件响应部分,后执行下方的中间件响应部分

    出现这种顺序是由于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()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面利用完整代码演示中间件的使用及顺序问题

    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)
    
    • 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

    执行结果满足上方的分析过程:
    在这里插入图片描述在这里插入图片描述

    如果你使用了 yield 关键字依赖, 依赖中的退出代码将在执行中间件后执行.
    如果有任何后台任务(稍后记录), 它们将在执行中间件后运行.

  • 相关阅读:
    Go语言的100个错误使用场景(21-29)|数据类型
    自然语言处理学习笔记(九)———— OVV Recall Rate与 IV Recall Rate
    C++核心编程 day09 类型转换、异常、输入输出流
    SpringMVC之CRUD(直接让你迅速完成部署)
    Java--SpringMVC概述,运行流程
    【JS函数】JS函数之高阶函数、组合函数、函数柯里化
    2023Fiddler抓包学习笔记 -- 环境配置及工具栏介绍
    centos7下nginx的安装与配置
    centos6服务器升级glibc失败后操作系统命令不能执行处理
    mysqldump常用操作示例/命令
  • 原文地址:https://blog.csdn.net/baidu_38766791/article/details/127453579