Skip to content

Commit dedb5ec

Browse files
committed
Middleware to cache when a POST hasn't been made.
1 parent 92e1689 commit dedb5ec

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

sapling/utils/middleware.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from django.middleware.cache import UpdateCacheMiddleware
2+
3+
from django.utils.cache import learn_cache_key, get_max_age
4+
5+
6+
class UpdateCacheMiddlewareNoHeaders(UpdateCacheMiddleware):
7+
"""
8+
Just like UpdateCacheMiddleware but we don't set cache headers in the
9+
HTTP response.
10+
"""
11+
def process_response(self, request, response):
12+
"""Sets the cache, if needed."""
13+
if not self._should_update_cache(request, response):
14+
# We don't need to update the cache, just return.
15+
return response
16+
if not response.status_code == 200:
17+
return response
18+
# Try to get the timeout from the "max-age" section of the "Cache-
19+
# Control" header before reverting to using the default cache_timeout
20+
# length.
21+
timeout = get_max_age(response)
22+
if timeout == None:
23+
timeout = self.cache_timeout
24+
elif timeout == 0:
25+
# max-age was set to 0, don't bother caching.
26+
return response
27+
#patch_response_headers(response, timeout)
28+
if timeout:
29+
cache_key = learn_cache_key(
30+
request, response, timeout, self.key_prefix, cache=self.cache)
31+
if hasattr(response, 'render') and callable(response.render):
32+
response.add_post_render_callback(
33+
lambda r: self.cache.set(cache_key, r, timeout)
34+
)
35+
else:
36+
self.cache.set(cache_key, response, timeout)
37+
return response
38+
39+
40+
class UpdateCacheMiddlewareNoEdit(UpdateCacheMiddleware):
41+
"""
42+
Just like UpdateCacheMiddleware but don't cache anything from anyone
43+
who has the 'has_POSTed' session flag. We use this because the default
44+
CACHE_MIDDLEWARE_ANONYMOUS_ONLY will still cache non-logged in users'
45+
edits, etc. So we sort of say that 'anonymous,' in our case, is really
46+
anyone who's never made an edit.
47+
"""
48+
def _should_update_cache(self, request, response):
49+
if (not hasattr(request, '_cache_update_cache') or
50+
not request._cache_update_cache):
51+
return False
52+
# If the session has not been accessed otherwise, we don't want to
53+
# cause it to be accessed here. If it hasn't been accessed, then the
54+
# user's logged-in status has not affected the response anyway.
55+
if self.cache_anonymous_only and self._session_accessed(request):
56+
assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."
57+
if request.user.is_authenticated() or request.session.get('has_POSTed'):
58+
# Don't cache user-variable requests from authenticated users.
59+
return False
60+
return True
61+
62+
63+
class UpdateCacheMiddleware(UpdateCacheMiddlewareNoEdit, UpdateCacheMiddlewareNoHeaders):
64+
pass
65+
66+
67+
class TrackPOSTMiddleware(object):
68+
def process_request(self, request):
69+
if request.method == 'POST' and 'has_POSTed' not in request.session:
70+
request.session['has_POSTed'] = True

0 commit comments

Comments
 (0)