gzip.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import re
  2. from django.utils.text import compress_string
  3. from django.utils.cache import patch_vary_headers
  4. re_accepts_gzip = re.compile(r'\bgzip\b')
  5. class GZipMiddleware(object):
  6. """
  7. This middleware compresses content if the browser allows gzip compression.
  8. It sets the Vary header accordingly, so that caches will base their storage
  9. on the Accept-Encoding header.
  10. """
  11. def process_response(self, request, response):
  12. # It's not worth attempting to compress really short responses.
  13. if len(response.content) < 200:
  14. return response
  15. patch_vary_headers(response, ('Accept-Encoding',))
  16. # Avoid gzipping if we've already got a content-encoding.
  17. if response.has_header('Content-Encoding'):
  18. return response
  19. # MSIE have issues with gzipped response of various content types.
  20. if "msie" in request.META.get('HTTP_USER_AGENT', '').lower():
  21. ctype = response.get('Content-Type', '').lower()
  22. if not ctype.startswith("text/") or "javascript" in ctype:
  23. return response
  24. ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
  25. if not re_accepts_gzip.search(ae):
  26. return response
  27. # Return the compressed content only if it's actually shorter.
  28. compressed_content = compress_string(response.content)
  29. if len(compressed_content) >= len(response.content):
  30. return response
  31. response.content = compressed_content
  32. response['Content-Encoding'] = 'gzip'
  33. response['Content-Length'] = str(len(response.content))
  34. return response