starlette icon indicating copy to clipboard operation
starlette copied to clipboard

Add `ZstdMiddleware`

Open Kludex opened this issue 2 months ago • 3 comments

It has been some time since #2564, but I think it makes sense to bring more of those algorithms into Starlette - at least zstd, since now it's on the stdlib.

I think an API that supports different compression methods makes sense, but on #2564, the API tried to add 3 of them in a single CompressMiddleware, I think the API we want to achieve is something like this:

CompressionMiddleware("gzip", minimum_size=500, compresslevel=3)
CompressionMiddleware("zstd", minimum_size=500, compresslevel=3)
CompressionMiddleware(MyOwnResponderObject(), ...)

What do you think @Zaczero ?

Kludex avatar Oct 11 '25 10:10 Kludex

I think that:

Most users will want it to just work with minimal setup. Having them configure different middlewares for the same concept isn't good UX. It also makes stack traces slightly deeper and harder to read. I believe a single, well-designed master middleware with good configuration options is the better approach.

Most users will expect sane defaults. For example, the current content-type defaults are too limited. I'm envisioning a smooth out-of-the-box experience - these defaults are standard across many software and mostly a solved problem. Setting them properly should let users enjoy the "fast API" experience without needing to understand the details.

It would be great to support brotli compression, since gzip, brotli, and zstd have become the de facto standards. That said, I see brotli as less important than gzip or zstd.

This is reflected in my starlette-compress package. Personally, I'd take that code and adapt it slightly to make adding custom compression methods easy - perhaps via an extensions=... argument of dict[str, compressor]. Only a small fraction of users will ever need to extend it; most will just rely on the standard algorithms, which rarely change in the first place.

Zaczero avatar Oct 11 '25 11:10 Zaczero

Maybe something like the following?

CompressionMiddleware(
    # Global settings
    minimum_size=500, 
    compresslevel=3,
    # Specific settings 
    gzip={"enable": False},
    zstd={"compresslevel": 9}
    # User defined
    extra_compressors={"potato": PotatoResponder()}
)

Kludex avatar Oct 19 '25 10:10 Kludex

@Kludex That seems really good. I think gzip/zstd could accept either dict or simple boolean for the common case of disabling certain compression:

gzip={"somesetting": 9},  # changes config
or
gzip=False,  # disables

Zaczero avatar Oct 29 '25 12:10 Zaczero