如何编写自定义 FastAPI 中间件 class

How to write a custom FastAPI middleware class

我已经阅读了 FastAPI 关于中间件的文档(特别是 middleware tutorial, the CORS middleware section and the advanced middleware 指南),但找不到如何编写中间件 class 的具体示例,您可以使用 add_middleware 函数(与使用装饰器添加的基本中间件函数相反)在本网站上也没有。

我更喜欢使用 add_middleware 而不是基于应用程序的装饰器的原因是我想在一个共享库中编写一个中间件,它将被多个不同的项目使用,因此我不能绑定它到特定的 FastAPI 实例。

所以我的问题是:你是怎么做到的?

因为 FastAPI 实际上也是 Starlette underneath, you could use BaseHTTPMiddleware that allows you to implement a middleware class (you may want to have a look at this post)。下面给出了相同方法的两种变体,其中 add_middleware() 函数用于添加中间件 class.

选项 1

middleware.py

from fastapi import Request

class MyMiddleware:
    def __init__(
            self,
            some_attribute: str,
    ):
        self.some_attribute = some_attribute

    async def __call__(self, request: Request, call_next):
        # do something with the request object
        content_type = request.headers.get('Content-Type')
        print(content_type)
        
        # process the request and get the response    
        response = await call_next(request)
        
        return response

app.py

from fastapi import FastAPI
from middleware import MyMiddleware
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()
my_middleware = MyMiddleware(some_attribute="some_attribute_here_if_needed")
app.add_middleware(BaseHTTPMiddleware, dispatch=my_middleware)

选项 2

middleware.py

from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware

class MyMiddleware(BaseHTTPMiddleware):
    def __init__(
            self,
            app,
            some_attribute: str,
    ):
        super().__init__(app)
        self.some_attribute = some_attribute

    async def dispatch(self, request: Request, call_next):
        # do something with the request object, for example
        content_type = request.headers.get('Content-Type')
        print(content_type)
        
        # process the request and get the response    
        response = await call_next(request)
        
        return response

app.py

from fastapi import FastAPI
from middleware import MyMiddleware

app = FastAPI()
app.add_middleware(MyMiddleware, some_attribute="some_attribute_here_if_needed")