fastapi 的 middleware 怎么改成同步模式?

fastapi 的 middleware 怎么改成同步模式?

我想写一个验证身份的中间件

@app.middleware("http")

async def get_user_id(request: Request, call_next):

from core.mysql.models import SessionTable

from core.mysql.models import SessionTable

from core.mysql.models import UserTable

from apps.user.schemas import User

from playhouse.shortcuts import model_to_dict

session_key = request.cookies.get("session_key")

if session_key:

try:

session: SessionTable | None = SessionTable.get_or_none(

session_key=session_key)

if session:

user_id = session.user_id

if user_id:

request.state.user_id = user_id

user: UserTable | None = UserTable.get_or_none(id=user_id)

request.state.user = User(**model_to_dict(user))

except Exception as error:

logger.warning(error)

if not session_key or not request.state.get('user_id', None):

return Response(status_code=401, content='Invalid token')

response = call_next(request)

return response

但是有一个问题,就是中间件的函数,必须要加 async,这样就变成了一个同步函数了

非常的令人讨厌!

我不喜欢异步,因为我用的 peewee 等库都不支持异步

比如我们需要在 middleware 中使用 pymysql、redis-py 这些同步库的时候,就会有麻烦

怎么让中间件不加 async?


如果我把 def get_user_id 前面的 async 删掉的话,就会报错

ERROR:    Exception in ASGI application

Traceback (most recent call last):

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py", line 429, in run_asgi

result = await app( # type: ignore[func-returns-value]

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__

return await self.app(scope, receive, send)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/fastapi/applications.py", line 276, in __call__

await super().__call__(scope, receive, send)

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/starlette/applications.py", line 122, in __call__

await self.middleware_stack(scope, receive, send)

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/starlette/middleware/errors.py", line 184, in __call__

raise exc

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/starlette/middleware/errors.py", line 162, in __call__

await self.app(scope, receive, _send)

File "/Users/ponponon/.local/share/virtualenvs/whoisface-dx42pPyK/lib/python3.11/site-packages/starlette/middleware/base.py", line 108, in __call__

response = await self.dispatch_func(request, call_next)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

TypeError: object Response can't be used in 'await' expression


回答:

from fastapi import FastAPI, Request, Response

from starlette.concurrency import run_in_threadpool

app = FastAPI()

def sync_code():

# 这里放你的同步代码

pass

@app.middleware("http")

async def sync_middleware(request: Request, call_next):

await run_in_threadpool(sync_code)

response = await call_next(request)

return response

你删掉了async,自然就会报错,因为你下面的代码用了await,中间件是要异步的,你试试上面的方法

以上是 fastapi 的 middleware 怎么改成同步模式? 的全部内容, 来源链接: utcz.com/p/938936.html

回到顶部