python:Fastapi – Middleware(中间件)

简单唠一些

最近有些忙,时间不怎富裕,学习总结也落下了,今天总结了一些,咱们继续书接上文。

继上篇文章主要唠了安全性的一部分知识(后续再补一些知识),今天主要聊下中间件。

  • FastAPI中的 “中间件” 是一个函数,它在每个请求被特定的路径操作处理之前,以及在每个响应返回之前工作。


  • 中间件

    中间件(英语:Middleware),又译中间件、中介层,是一类提供系统软件和应用软件之间连接、便于软件各部件之间的沟

    通的软件,应用软件可以借助中间件在不同的技术架构之间共享信息与资源。

    而在Fastapi中的中间件是一个函数,用于处理每一请求路径操作之前,以及每个响应返回之前工作。它接收你应用程序的每

    一个请求。它可以对这些请求做一些事情或执行任何需要的代码。它将通过某种路径操作将请求传递给应用程序的其他部分。它

    还可以通过某种路径操作获取应用程序生产的响应,可以对该响应做些什么或者执行任何需要的代码,然后返回该响应。

    import timeimport uvicornfrom fastapi import statusfrom fastapi import Requestfrom fastapi import FastAPIfrom pydantic import BaseModelfrom typing import Optionalfrom fastapi import Responseapp = FastAPI()@app.middleware("http")async def add_time_header(request: Request, call_):    start_time = time.time()    if request.method == "POST":        print(request.url)    response: Response = await call_(request)    process_time = time.time() - start_time    response.headers["X-Process-Time"] = str(process_time)    response.status_code = status.HTTP_201_CREATED    return responseclass Item(BaseModel):    name: str    description: str = "a description message!"    cc: Optional[str] = "2"@app.post("/items/", response_model=Item)async def read_item(item: Item):    return itemif __name__ == '__main__':    uvicorn.run("middleware_main:app", debug=True)

  • 使用@app.middleware(“http”)装饰器创建中间件
  •     def middleware(self, middleware_type: str) -> typing.Callable:        # 源码        assert (            middleware_type == "http"        ), 'Currently only middleware("http") is supported. 目前只支持中间件(“http”)。'        def decorator(func: typing.Callable) -> typing.Callable:            self.add_middleware(BaseHTTPMiddleware, dispatch=func)            return func        return decorator

    源码这里写的其实就是含局部函数的方法,先assert断言是不是http,断言正确就执行局部函数decorator,否则就抛出AssertionError: Currently only middleware(“http”) is supported.


  • request: Request是请求参数

  • if request.method == “POST”:判断是什么类型的请求方式
  •     if request.method == "POST":        print(request.url)

  • call_ 传递request给相应的路径操作,然后从路径操作中返回response
  • call_这名称是可自定义的,但是最好就按这个默认写法call_next
  • call_底层实际调用的是BaseHTTPMiddleware类:

    <coroutine object BaseHTTPMiddleware.__call__.<locals>.call_next at 0x0000015ADA9219A0>

    BaseHTTPMiddleware类的部分源码:

    class BaseHTTPMiddleware:    def __init__(self, app: ASGIApp, dispatch: DispatchFunction = None) -> None:        self.app = app        self.dispatch_func = self.dispatch if dispatch is None else dispatch    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:        if scope["type"] != "http":            await self.app(scope, receive, send)            return        async def call_next(request: Request) -> Response:            app_exc: typing.Optional[Exception] = None            send_stream, recv_stream = anyio.create_memory_object_stream()

    response 的前和后

    在任何路径操作收到request前,可以添加要和请求一起运行的代码。当然也可以在响应生成但是返回之前添加代码.

    可以添加自定义请求头 X-Process-Time 包含以秒为单位的接收请求和生成响应的时间:

        # 往返回的头信息中增加一个参数    response.headers["X-Process-Time"] = str(process_time)    # 重新被赋值状态码    response.status_code = status.HTTP_201_CREATED

    运行结果-截图如下:


    今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!

    未完成,待续……

    一直在努力,希望你也是!

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2022年2月18日
    下一篇 2022年2月18日

    相关推荐