Search code examples
pythonfastapimiddlewarestarlette

Custom FastAPI middleware causes LocalProtocolError("Too much data for declared Content-Length") exception


I have a middleware implemented for FastAPI. For responses that includes some content, it works perfectly. But if a response has no body, it is causing LocalProtocolError("Too much data for declared Content-Length") exception.

To isolate the problem, I've reduced the middleware class to this:

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)

It basically does nothing.

When I add the middleware, I have an exception:

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

When I disable the middleware, I have no problem.

Here is the line that creates the response which triggers the exception:

return Response(status_code=HTTP_204_NO_CONTENT)

To further debug the problem, I've activated a breakpoint in the h11/_writers.py ContentLengthWriter class, where the actual exception occurs.

I've tried to decode the byte stream with utf-8 and cp437, but had no luch.

 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)

I'm stopping the code at this line: self._length -= len(data)

If the middleware is disabled, data looks like this: b''

If the middleware is enabled, data looks like this: b'\x1f\x8b\x08\x00\xf6God\x02\xff'

What would be modifying the content of the response?


Solution

  • I've solved it. I've just changed the order of which middlewares are added. When I moved my middleware after the GZIP middleware, problem disappeared.

    Thanks to MatsLindh for pointing out that it is a gzip header.