diff --git a/docs/middleware/gzip.md b/docs/middleware/gzip.md new file mode 100644 index 0000000..9110692 --- /dev/null +++ b/docs/middleware/gzip.md @@ -0,0 +1,20 @@ +# Gzip compress middleware + +```python +from spiderweb import SpiderwebRouter + +app = SpiderwebRouter( + middleware=["spiderweb.middleware.gzip"], +) +``` +When your response is big, you maybe want to reduce traffic between +server and client. + +Gzip will help you. This middleware do not cover all possibilities of content compress. Brotli, deflate, zsts or other are out of scope. + +This version only check if gzip method is accepted by client, size of content is greater than 500 bytes. Check if response is not already compressed and response status is between 200 and 300. + + +> [!NOTE] +> Minimal required version is 1.3.1 + diff --git a/spiderweb/middleware/gzip.py b/spiderweb/middleware/gzip.py new file mode 100644 index 0000000..cdf55a1 --- /dev/null +++ b/spiderweb/middleware/gzip.py @@ -0,0 +1,36 @@ + +""" + Source code inspiration :https://github.com/colour-science/flask-compress/blob/master/flask_compress/flask_compress.py +""" + + +from spiderweb.middleware import SpiderwebMiddleware +from spiderweb.request import Request +from spiderweb.response import HttpResponse + + +import gzip + + +class GzipMiddleware(SpiderwebMiddleware): + + algorithm = "gzip" + minimum_length = 500 + + def post_process(self, request: Request, response: HttpResponse, rendered_response: str) -> str: + + #right status, length > 500, instance string (because FileResponse returns list of bytes , + # not already compressed, and client accepts gzip + if not (200 <= response.status_code < 300) or \ + len(rendered_response) < self.minimum_length or \ + not isinstance(rendered_response, str) or \ + self.algorithm in response.headers.get("Content-Encoding", "") or \ + self.algorithm not in request.headers.get("Accept-Encoding", ""): + return rendered_response + + zipped = gzip.compress(rendered_response.encode('UTF-8')) + response.headers["Content-Encoding"] = self.algorithm + response.headers["Content-Length"] = str(len(zipped)) + + return zipped +