1 from django.conf import settings
2 from django.utils.cache import patch_vary_headers
3 from django.middleware import locale
4 from .serializers import json_decode, json_encode
5 from .variables import SsiVariable, provide_vars
9 class PrepareForCacheMiddleware(object):
11 def process_response(request, response):
12 if getattr(request, 'ssi_vars_needed', None):
13 vars_needed = {k: v.definition
14 for (k, v) in request.ssi_vars_needed.items()}
15 response['X-Ssi-Vars-Needed'] = json_encode(
16 vars_needed, sort_keys=True)
20 class SsiMiddleware(object):
21 def process_request(self, request):
22 request.ssi_vary = set()
23 #request.ssi_cache_control_after = set()
25 def process_view(self, request, view_func, view_args, view_kwargs):
26 request.ssi_vars_needed = {}
28 def _process_rendered_response(self, request, response):
29 # Prepend the SSI variables.
30 if hasattr(request, 'ssi_vars_needed'):
31 vars_needed = request.ssi_vars_needed
33 vars_needed = json_decode(response.get('X-Ssi-Vars-Needed', '{}'))
34 vars_needed = {k: SsiVariable(*v)
35 for (k, v) in vars_needed.items()}
38 response.content = provide_vars(request, vars_needed) + \
41 # Add the Vary headers declared by all the SSI vars.
42 patch_vary_headers(response, sorted(request.ssi_vary))
43 # TODO: cache control?
45 # With a cached response, CsrfViewMiddleware.process_response
46 # was never called, so if we used the csrf token, we must do
47 # its job of setting the csrf token cookie on our own.
48 if (not getattr(request, 'csrf_processing_done', False)
49 and request.META.get("CSRF_COOKIE_USED", False)):
50 response.set_cookie(settings.CSRF_COOKIE_NAME,
51 request.META["CSRF_COOKIE"],
52 max_age=getattr(settings, 'CSRF_COOKIE_AGE',
53 60 * 60 * 24 * 7 * 52),
54 domain=settings.CSRF_COOKIE_DOMAIN,
55 path=settings.CSRF_COOKIE_PATH,
56 secure=settings.CSRF_COOKIE_SECURE,
57 httponly=settings.CSRF_COOKIE_HTTPONLY
59 request.csrf_processing_done = True
61 def process_response(self, request, response):
62 if hasattr(response, 'render') and callable(response.render):
63 response.add_post_render_callback(
64 lambda r: self._process_rendered_response(request, r)
67 self._process_rendered_response(request, response)
70 from .middleware_debug import DebugUnSsiMiddleware
71 response = DebugUnSsiMiddleware().process_response(
77 class LocaleMiddleware(locale.LocaleMiddleware):
79 Version of the LocaleMiddleware for use together with the
80 SsiMiddleware if USE_I18N or USE_L10N is set.
82 Stock LocaleMiddleware looks for user language selection in
83 the session data and cookies, before it falls back to parsing
84 Accept-Language. The effect of accessing the session is adding
85 the `Vary: Cookie` header to the response. While this is correct
86 behaviour, it renders the cache system useless (see
87 https://code.djangoproject.com/ticket/13217).
89 This version of LocaleMiddleware doesn't mark the session
90 as accessed on every request, so SessionMiddleware doesn't add the
91 Vary: Cookie header (unless something else actually uses the session
92 in a meaningful way, of course). Instead, it tells SsiMiddleware
93 to add the Vary: Cookie header to the final response.
96 def process_request(self, request):
97 if hasattr(request, 'session'):
98 session_accessed_before = request.session.accessed
100 session_accessed_before = None
101 super(LocaleMiddleware, self).process_request(request)
102 if session_accessed_before is False:
103 if (request.session.accessed and
104 (settings.USE_I18N or settings.USE_L10N)):
105 request.session.accessed = False
106 request.ssi_vary.add('Cookie')