-
Notifications
You must be signed in to change notification settings - Fork 2k
perf: enable gzip. #2422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: enable gzip. #2422
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# coding=utf-8 | ||
""" | ||
@project: MaxKB | ||
@Author:虎 | ||
@file: gzip.py | ||
@date:2025/2/27 10:03 | ||
@desc: | ||
""" | ||
from django.utils.cache import patch_vary_headers | ||
from django.utils.deprecation import MiddlewareMixin | ||
from django.utils.regex_helper import _lazy_re_compile | ||
from django.utils.text import compress_sequence, compress_string | ||
|
||
re_accepts_gzip = _lazy_re_compile(r"\bgzip\b") | ||
|
||
|
||
class GZipMiddleware(MiddlewareMixin): | ||
""" | ||
Compress content if the browser allows gzip compression. | ||
Set the Vary header accordingly, so that caches will base their storage | ||
on the Accept-Encoding header. | ||
""" | ||
|
||
max_random_bytes = 100 | ||
|
||
def process_response(self, request, response): | ||
if request.method != 'GET' or request.path.startswith('/api'): | ||
return response | ||
# It's not worth attempting to compress really short responses. | ||
if not response.streaming and len(response.content) < 200: | ||
return response | ||
|
||
# Avoid gzipping if we've already got a content-encoding. | ||
if response.has_header("Content-Encoding"): | ||
return response | ||
|
||
patch_vary_headers(response, ("Accept-Encoding",)) | ||
|
||
ae = request.META.get("HTTP_ACCEPT_ENCODING", "") | ||
if not re_accepts_gzip.search(ae): | ||
return response | ||
|
||
if response.streaming: | ||
if response.is_async: | ||
# pull to lexical scope to capture fixed reference in case | ||
# streaming_content is set again later. | ||
orignal_iterator = response.streaming_content | ||
|
||
async def gzip_wrapper(): | ||
async for chunk in orignal_iterator: | ||
yield compress_string( | ||
chunk, | ||
max_random_bytes=self.max_random_bytes, | ||
) | ||
|
||
response.streaming_content = gzip_wrapper() | ||
else: | ||
response.streaming_content = compress_sequence( | ||
response.streaming_content, | ||
max_random_bytes=self.max_random_bytes, | ||
) | ||
# Delete the `Content-Length` header for streaming content, because | ||
# we won't know the compressed size until we stream it. | ||
del response.headers["Content-Length"] | ||
else: | ||
# Return the compressed content only if it's actually shorter. | ||
compressed_content = compress_string( | ||
response.content, | ||
max_random_bytes=self.max_random_bytes, | ||
) | ||
if len(compressed_content) >= len(response.content): | ||
return response | ||
response.content = compressed_content | ||
response.headers["Content-Length"] = str(len(response.content)) | ||
|
||
# If there is a strong ETag, make it weak to fulfill the requirements | ||
# of RFC 9110 Section 8.8.1 while also allowing conditional request | ||
# matches on ETags. | ||
etag = response.get("ETag") | ||
if etag and etag.startswith('"'): | ||
response.headers["ETag"] = "W/" + etag | ||
response.headers["Content-Encoding"] = "gzip" | ||
|
||
return response | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,7 +55,7 @@ | |
'django.contrib.sessions.middleware.SessionMiddleware', | ||
'django.middleware.common.CommonMiddleware', | ||
'django.contrib.messages.middleware.MessageMiddleware', | ||
'django.middleware.gzip.GZipMiddleware', | ||
'common.middleware.gzip.GZipMiddleware', | ||
'common.middleware.static_headers_middleware.StaticHeadersMiddleware', | ||
'common.middleware.cross_domain_middleware.CrossDomainMiddleware' | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The provided code looks generally correct for setting up middleware in Django. However, there are a few potential areas to consider:
Here’s an improved version with these considerations addressed: 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.staticfiles.middleware.StaticFilesMiddleware', # Static files middleware must come first
'compressionmiddleware.middleware.CompressionMiddleware', # Replace with appropriate gzip library
'common.middleware.gzip.GZipMiddleware',
'common.middleware.static_headers_middleware.StaticHeadersMiddleware',
'common.middleware.cross_domain_middleware.CrossDomainMiddleware' If you're using a specific third-party module for GZIP compression, make sure to replace |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reviewing the provided code snippet, I have identified several areas that could be improved:
Import Order: The import statements are alphabetical, which can sometimes make them harder to read.
Variable Naming: Variable names like
re_accepts_gzip
,max_random_bytes
, etc., follow Django's naming conventions well but should be consistent across similar contexts.Code Duplication: There is duplicated code between the non-streaming and streaming paths in the
process_response
method. This can be cleaned up by using a single function for both cases.Error Handling: While not explicitly mentioned, handling exceptions during compression might improve robustness.
Comments: Some parts of the code could benefit from more detailed comments explaining what each section does.
Here is an optimized version of the code based on these points:
Key Changes Made:
_apply_gzip_compression
.zlib
instead of custom byte manipulation for better functionality and performance.asyncio
where necessary.This refactoring enhances readability and maintainability while ensuring efficient gzip compression for user agents supporting it.