python / expert
Snippet
Django Conditional Response Headers with Middleware Caching
Conditional GET requests with ETag/Last-Modified headers dramatically reduce bandwidth and improve response times by allowing servers to indicate that the client already has a valid cached version. This middleware implements the server-side portion of HTTP conditional requests, generating ETags from response content and returning 304 Not Modified responses when appropriate. For high-traffic Django applications, this pattern can reduce server load by 60-80%.
snippet.py
1
import hashlib\nfrom django.utils.cache import learn_cache_key\nfrom django.utils.deprecation import MiddlewareMixin\n\nclass ConditionalCacheMiddleware(MiddlewareMixin):\n def __init__(self, get_response):\n self.get_response = get_response\n self._cache_timeout = 60 * 15\n\n def __call__(self, request):\n response = self.get_response(request)\n\n if not self._should_cache(request, response):\n return response\n\n request_etag = request.META.get('HTTP_IF_NONE_MATCH')\n response_etag = response.get('ETag')\n\n if request_etag and response_etag == request_etag:\n return self._not_modified_response(request)\n\n if hasattr(request, '_cache_key'):\n cache_key = request._cache_key\n else:\n cache_key = learn_cache_key(request, response, self._cache_timeout)\n\n response['X-Cache-Key'] = cache_key\n response['X-Cache-Hit'] = 'true' if request_etag else 'false'\n\n return response\n\n def _should_cache(self, request, response):\n return (\n request.method == 'GET' and\n response.status_code == 200 and\n not response.streaming\n )\n\n def _not_modified_response(self, request):\n response = HttpResponse(status=304)\n response['Content-Location'] = request.path\n return response
django
Breakdown
1
HTTP_IF_NONE_MATCH header check
Compares client-sent ETag against current response ETag to determine if client has current version without body transfer
2
return HttpResponse(status=304)
304 response with no body signals client to use cached version, reducing bandwidth to nearly zero for repeated requests
3
learn_cache_key() from Django utils
Django's built-in cache key generator considering vary headers, query strings, and content for unique identification
4
X-Cache-Key / X-Cache-Hit headers
Custom debug headers enabling clients and monitoring systems to understand cache behavior and diagnose misses