Hi all,
There is `GZipMiddleware` that compresses response bodies using gzip.
https://github.com/django/django/blob/main/django/middleware/gzip.pyBut there are other algorithms supported by browsers (e.g., Brotli).
At the moment, if somebody wants to add support for any of them in a
Django project, one has to create a new middleware class redefining
all the logic processing responses.
I propose simplifying the process by creating
`BaseCompressionMiddleware`. Its subclasses would just need to define
a tuple of supported compressors.
The tuple elements could be instances of such a data class:
```
@dataclass
class Compressor:
name: str
compress_string_func: Callable[[bytes], bytes]
compress_sequence_func: Optional[
Callable[[Iterable[bytes]], Iterator[bytes]]
] = None
def is_accepted_by(self, accept_encoding):
return bool(re.search(rf'\b{
self.name}\b', accept_encoding))
```
And the class could select a compressor using such code:
```
@classmethod
def select_compressor(cls, request, response):
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
for compressor in cls.compressors:
if (
compressor.is_accepted_by(ae)
and (not response.streaming or compressor.compress_sequence_func)
):
return compressor
```
Note, in the example `compress_string_func` is required and
`compress_sequence_func` is optional. I think that
`compress_string_func` would usually be a library function, and
`compress_sequence_func` would require some custom logic. And we
should not force users to define the latter.
`GZipMiddleware` could be changed to
```
gzip_compressor = Compressor(
name='gzip',
compress_string_func=compress_string,
compress_sequence_func=compress_sequence,
)
class GZipMiddleware(BaseCompressionMiddleware):
compressors = (gzip_compressor,)
```
And someone wanting to support both Brotli and gzip could define:
```
import brotli
from django.middleware.gzip import gzip_compressor
brotli_compressor = Compressor(
name='br',
compress_string_func=brotli.compress,
)
class CompressionMiddleware(BaseCompressionMiddleware)
compressors = (brotli_compressor, gzip_compressor)
```
Please let me know what you think about such an enhancement.
I will be happy to create a pull request if this is accepted.
Thanks,
Illia