0

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?

SercioSoydanov
  • 980
  • 10
  • 29
  • 1
    `\x1f\x8b\x08` is a gzip header, so do you have gzip compression involved somewhere in the chain? – MatsLindh May 25 '23 at 11:53
  • Yes actually I do, but what I can't figure out is how does the middleware effect this header. – SercioSoydanov May 25 '23 at 11:54
  • Hi @MatsLindh. Thanks to you pointing out that it iz a gzip header, I've solved the problem. One question though, how did you figure out that it was a gzip header? – SercioSoydanov May 26 '23 at 07:17
  • 1
    The bytes represented by `\x1f\x8b\x08` is the binary header of a gzip stream, which identifies it as gzip with deflate used for compression: https://en.wikipedia.org/wiki/Gzip#File_format - "a 10-byte header, containing a magic number (1f 8b), the compression method (08 for DEFLATE)," (so `\x1f\x8b\x08`) – MatsLindh May 26 '23 at 07:56

1 Answers1

0

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.

SercioSoydanov
  • 980
  • 10
  • 29