python 自定义FastAPI中间件导致LocalProtocolError(“Too much data for declared Content-Length”)异常

rsl1atfo  于 2023-05-27  发布在  Python
关注(0)|答案(1)|浏览(992)

我为FastAPI实现了一个中间件。对于包含一些内容的响应,它可以完美地工作。但是如果一个响应没有body,就会导致LocalProtocolError("Too much data for declared Content-Length")异常。
为了隔离问题,我将中间件类缩减为:

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

class LanguageManagerMiddleware(BaseHTTPMiddleware):

    def __init__(self, app: FastAPI):
        super().__init__(app)

    async def dispatch(self, request: Request, call_next) -> None:

        return await call_next(request)

它基本上什么都不做。
当我添加中间件时,我有一个例外:

raise LocalProtocolError("Too much data for declared Content-Length")
h11._util.LocalProtocolError: Too much data for declared Content-Length

当我禁用中间件时,我没有问题。
下面是创建触发异常的响应的代码行:

return Response(status_code=HTTP_204_NO_CONTENT)

为了进一步调试这个问题,我在h11/_writers.pyx 1 m2n1x类中激活了一个断点,实际的异常发生在这个断点上。
我试着用utf-8和cp 437解码字节流,但没有成功。

class ContentLengthWriter(BodyWriter):
        def __init__(self, length: int) -> None:
            self._length = length
    
        def send_data(self, data: bytes, write: Writer) -> None:
            self._length -= len(data)
            if self._length < 0:
                raise LocalProtocolError("Too much data for declared Content-Length")
            write(data)

我在这一行停止代码:self._length -= len(data)
如果中间件被禁用data看起来像这样:b''
如果中间件是启用的,data看起来像这样:b'\x1f\x8b\x08\x00\xf6God\x02\xff'
如何修改响应的内容?

xe55xuns

xe55xuns1#

我已经解决了我刚刚更改了添加中间件的顺序。当我把中间件移到GZIP中间件之后,问题就消失了。
感谢MatsLindh指出它是一个gzip头文件。

相关问题