You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041
  1. from django.utils.cache import (
  2. cc_delim_re, get_conditional_response, set_response_etag,
  3. )
  4. from django.utils.deprecation import MiddlewareMixin
  5. from django.utils.http import parse_http_date_safe
  6. class ConditionalGetMiddleware(MiddlewareMixin):
  7. """
  8. Handle conditional GET operations. If the response has an ETag or
  9. Last-Modified header and the request has If-None-Match or If-Modified-Since,
  10. replace the response with HttpNotModified. Add an ETag header if needed.
  11. """
  12. def process_response(self, request, response):
  13. # It's too late to prevent an unsafe request with a 412 response, and
  14. # for a HEAD request, the response body is always empty so computing
  15. # an accurate ETag isn't possible.
  16. if request.method != 'GET':
  17. return response
  18. if self.needs_etag(response) and not response.has_header('ETag'):
  19. set_response_etag(response)
  20. etag = response.get('ETag')
  21. last_modified = response.get('Last-Modified')
  22. last_modified = last_modified and parse_http_date_safe(last_modified)
  23. if etag or last_modified:
  24. return get_conditional_response(
  25. request,
  26. etag=etag,
  27. last_modified=last_modified,
  28. response=response,
  29. )
  30. return response
  31. def needs_etag(self, response):
  32. """Return True if an ETag header should be added to response."""
  33. cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
  34. return all(header.lower() != 'no-store' for header in cache_control_headers)