You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI自定义中间件调用await request.form()后无响应(连接超时)

FastAPI中间件调用request.form()后超时的问题解决

问题根源

在中间件中调用await request.form()会直接消耗请求体的数据流。FastAPI底层的Starlette框架中,请求体是流式且不可重复读取的。当后续call_next(request)把请求传递给业务路由时,路由尝试读取请求体时会发现没有数据,一直处于等待状态,最终导致连接超时。

解决办法

方法1:缓存请求体,允许重复读取

先读取请求体并缓存,再重新构建请求对象,确保下游路由能正常读取请求体:

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

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

    async def dispatch(self, request: Request, call_next):
        # 缓存原始请求体
        body = await request.body()
        # 替换请求内部的body缓存,让后续读取有效
        request._body = body
        
        await self.before_request(request)
        response = await call_next(request)
        self.after_request(request)
        print('call next executes')
        return response

    async def before_request(self, request: Request):
        try:
            print('------------------ before request starts ----------------')
            print(request.url)
            print(request.method)
            print(request.client.host)
            print(request.client.port)
            print(request.base_url)
            # 此时读取form不会消耗请求体
            form = await request.form()
            firstname = form.get('firstname')
            print(firstname)
            print('------------------ before request ends ----------------')
        except Exception as e:
            print(f'发生异常: {str(e)}')

    def after_request(self, request: Request):
        pass

方法2:将form数据存入request.state,下游直接复用

如果中间件读取form后,下游路由不需要再处理原始请求体,可将解析后的form数据存入request.state,下游直接取用即可:

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

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

    async def dispatch(self, request: Request, call_next):
        await self.before_request(request)
        response = await call_next(request)
        self.after_request(request)
        print('call next executes')
        return response

    async def before_request(self, request: Request):
        try:
            print('------------------ before request starts ----------------')
            print(request.url)
            print(request.method)
            print(request.client.host)
            print(request.client.port)
            print(request.base_url)
            form = await request.form()
            firstname = form.get('firstname')
            print(firstname)
            # 把form数据存入request.state,下游路由直接用
            request.state.form_data = form
            print('------------------ before request ends ----------------')
        except Exception as e:
            print(f'发生异常: {str(e)}')
            request.state.form_data = None

    def after_request(self, request: Request):
        pass

下游路由示例:

from fastapi import FastAPI, Request

app = FastAPI()
app.add_middleware(AuthMiddleWare, some_attribute="test")

@app.post("/test")
async def test(request: Request):
    return {"firstname": request.state.form_data.get("firstname") if request.state.form_data else None}

内容的提问来源于stack exchange,提问作者M. Mudassar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:00:27