Ticket #14560: fix_head_cache.diff
File fix_head_cache.diff, 6.7 KB (added by , 14 years ago) |
---|
-
django/middleware/cache.py
34 34 and effective way of avoiding the caching of the Django admin (and any other 35 35 user-specific content). 36 36 37 * This middleware expects that a HEAD request is answered with aresponse38 exactly like the corresponding GET request.37 * This middleware expects that a HEAD request is answered with the same response 38 headers exactly like the corresponding GET request. 39 39 40 40 * When a hit occurs, a shallow copy of the original response object is returned 41 41 from process_request. … … 71 71 if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache: 72 72 # We don't need to update the cache, just return. 73 73 return response 74 if request.method != 'GET':75 # This is a stronger requirement than above. It is needed76 # because of interactions between this middleware and the77 # HTTPMiddleware, which throws the body of a HEAD-request78 # away before this middleware gets a chance to cache it.79 return response80 74 if not response.status_code == 200: 81 75 return response 82 76 # Try to get the timeout from the "max-age" section of the "Cache- … … 90 84 return response 91 85 patch_response_headers(response, timeout) 92 86 if timeout: 93 cache_key = learn_cache_key(request, response, timeout, self.key_prefix)87 cache_key = learn_cache_key(request, response, timeout, '%s.%s' % (self.key_prefix, request.method)) 94 88 cache.set(cache_key, response, timeout) 95 89 return response 96 90 … … 123 117 request._cache_update_cache = False 124 118 return None # Don't cache requests from authenticated users. 125 119 126 cache_key = get_cache_key(request, self.key_prefix) 127 if cache_key is None: 128 request._cache_update_cache = True 129 return None # No cache information available, need to rebuild. 120 possible_cache_keys = [get_cache_key(request, '%s.%s' % (self.key_prefix, request.method))] 130 121 131 response = cache.get(cache_key, None) 132 if response is None: 133 request._cache_update_cache = True 134 return None # No cache information available, need to rebuild. 122 if request.method == 'HEAD': 123 possible_cache_keys.append(get_cache_key(request, '%s.%s' % (self.key_prefix, 'GET'))) 135 124 136 request._cache_update_cache = False 137 return response 125 for cache_key in possible_cache_keys: 126 if cache_key is None: 127 continue # Check another cache key. 138 128 129 response = cache.get(cache_key, None) 130 if response is None: 131 continue # Check another cache key. 132 133 request._cache_update_cache = False 134 return response 135 136 request.cache_update_cache = True 137 return None # No cache information available, need to rebuild. 138 139 139 class CacheMiddleware(UpdateCacheMiddleware, FetchFromCacheMiddleware): 140 140 """ 141 141 Cache middleware that provides basic behavior for many simple sites. -
tests/regressiontests/cache/tests.py
557 557 learn_cache_key(request, response) 558 558 self.assertEqual(get_cache_key(request), 'views.decorators.cache.cache_page.settingsprefix.a8c87a3d8c44853d7f79474f7ffe4ad5.d41d8cd98f00b204e9800998ecf8427e') 559 559 560 class CacheHEADTest(unittest.TestCase): 561 562 def setUp(self): 563 self.orig_cache_middleware_seconds = settings.CACHE_MIDDLEWARE_SECONDS 564 self.orig_cache_middleware_key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX 565 self.orig_cache_backend = settings.CACHE_BACKEND 566 settings.CACHE_MIDDLEWARE_SECONDS = 60 567 settings.CACHE_MIDDLEWARE_KEY_PREFIX = 'test' 568 settings.CACHE_BACKEND = 'locmem:///' 569 self.path = '/cache/test/' 570 571 def tearDown(self): 572 settings.CACHE_MIDDLEWARE_SECONDS = self.orig_cache_middleware_seconds 573 settings.CACHE_MIDDLEWARE_KEY_PREFIX = self.orig_cache_middleware_key_prefix 574 settings.CACHE_BACKEND = self.orig_cache_backend 575 576 def _get_request(self, method): 577 request = HttpRequest() 578 request.META = { 579 'SERVER_NAME': 'testserver', 580 'SERVER_PORT': 80, 581 } 582 request.method = method 583 request.path = request.path_info = self.path 584 return request 585 586 def _get_request_cache(self, method): 587 request = self._get_request(method) 588 request._cache_update_cache = True 589 return request 590 591 def _set_cache(self, request, msg): 592 response = HttpResponse() 593 response.content = msg 594 return UpdateCacheMiddleware().process_response(request, response) 595 596 def test_head_caches_correctly(self): 597 test_content = 'test content' 598 599 request = self._get_request_cache('HEAD') 600 self._set_cache(request, test_content) 601 602 request = self._get_request('HEAD') 603 get_cache_data = FetchFromCacheMiddleware().process_request(request) 604 self.assertNotEqual(get_cache_data, None) 605 self.assertEqual(test_content, get_cache_data.content) 606 607 def test_head_with_cached_get(self): 608 test_content = 'test content' 609 610 request = self._get_request_cache('GET') 611 self._set_cache(request, test_content) 612 613 request = self._get_request('HEAD') 614 get_cache_data = FetchFromCacheMiddleware().process_request(request) 615 self.assertNotEqual(get_cache_data, None) 616 self.assertEqual(test_content, get_cache_data.content) 617 560 618 class CacheI18nTest(unittest.TestCase): 561 619 562 620 def setUp(self): -
docs/topics/cache.txt
328 328 will be cached. This is a simple and effective way of disabling caching for any 329 329 user-specific pages (include Django's admin interface). Note that if you use 330 330 ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated 331 ``AuthenticationMiddleware``. 331 ``AuthenticationMiddleware``. The cache middleware expects that a HEAD request 332 is answered with the same response headers exactly like the corresponding GET 333 request, in that case it could return cached GET response for HEAD request. 332 334 333 335 Additionally, the cache middleware automatically sets a few headers in each 334 336 ``HttpResponse``: