Exemple #1
0
 def test_plain_views_are_cacheable(self, mocked_api_session):
     mocked_api_session().get().json.return_value = {
         'count':
         1,
         'results': [{
             'nomis_id': 'AAA',
             'short_name': 'Prison',
             'name': 'HMP Prison'
         }],
     }
     view_names = [
         'help_area:help', 'help_area:help-new-payment',
         'help_area:help-sent-payment', 'help_area:prison_list', 'terms',
         'privacy', 'js-i18n', 'sitemap_xml', 'accessibility'
     ]
     for view_name in view_names:
         response = self.client.get(reverse(view_name))
         self.assertGreaterEqual(get_max_age(response),
                                 3600,
                                 msg=f'{view_name} should be cacheable')
         with override_lang('cy'):
             response = self.client.get(reverse(view_name))
             self.assertGreaterEqual(get_max_age(response),
                                     3600,
                                     msg=f'{view_name} should be cacheable')
Exemple #2
0
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not self._should_update_cache(request, response):
         # We don't need to update the cache, just return.
         return response
     if request.method != 'GET':
         # This is a stronger requirement than above. It is needed
         # because of interactions between this middleware and the
         # HTTPMiddleware, which throws the body of a HEAD-request
         # away before this middleware gets a chance to cache it.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     patch_response_headers(response, timeout)
     if timeout:
         cache_key = learn_cache_key(request, response, timeout,
                                     self.key_prefix)
         cache.set(cache_key, response, timeout)
     return response
Exemple #3
0
    def process_response(self, request, response):
        """Set the cache, if needed."""
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response

        if response.streaming or response.status_code not in (200, 304):
            return response

        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
            return response

        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        patch_response_headers(response, timeout)
        if timeout and response.status_code == 200:
            cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout)
                )
            else:
                self.cache.set(cache_key, response, timeout)
        return response
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        #if not self._should_update_cache(request, response):
        #    # We don't need to update the cache, just return.
        #    return response

        if response.streaming or response.status_code != 200:
            return response
        
        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
            return response

        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout == None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        patch_response_headers(response, timeout)
        if timeout:
            cache_key = "%s-%s" % (self.key_prefix, request.get_full_path())
            #raise ValueError(cache_key)
            if hasattr(response, 'render') and isinstance(response.render, collections.Callable):
                response.add_post_render_callback(
                    lambda r: cache._cache.set(cache_key.encode("utf-8"), zlib.compress(r.content, 9), timeout)
                )
            else:
                # we use the highest compression level, because since it is cached we hope for it to pay off
                cache._cache.set(cache_key.encode("utf-8"), zlib.compress(response.content, 9), timeout)
        return response
Exemple #5
0
 def process_response(self, request, response):
     # Get the path (do it early since we do conditionals on it)
     path = request.get_full_path()
     
     anon_only = getattr(settings,"CACHE_MIDDLEWARE_ANONYMOUS_ONLY",False)
     
     # A few conditions that cause us not to cache.
     if request.method != "GET" \
       or not response.status_code == 200:
         return response
     
     # The cache key prefix (should match what is in the site's nginx config)
     prefix = getattr(settings,"NGINX_CACHE_PREFIX","NG")
     
     # See the value of max-age and set timer on that. If not set,
     # use CACHE_MIDDLEWARE_SECONDS. If 0, do not cache.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = getattr(settings,"CACHE_MIDDLEWARE_SECONDS",300)
     elif timeout == 0:
         return response
     
     # Set the item in cache.
     key = "%s:%s" % (prefix, path)
     cache.set(key, response.content, timeout)
     
     return response
    def wrapped_view(request, *args, **kwargs):

        # Build a cache key using only the view function and the arguments;
        # nothing related to the request or current site.
        view_path = '.'.join((view_func.__module__, view_func.__name__))
        signature = HashableTuple((args, kwargs)).hash
        cache_key = ':'.join((view_path, signature))

        # Retrieve the response from the cache, or generate a new one.
        if getattr(request, '_purging', False):
            response = None
        else:
            response = cache.get(cache_key)
        if response is None:
            response = view_func(request, *args, **kwargs)
            max_age = get_max_age(response)
            if max_age is not None:
                cache.set(cache_key, response, max_age)
        else:
            response['X-From-Cache'] = True

        # Stop the middleware from caching it too.
        request._cache_update_cache = False

        return response
Exemple #7
0
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not self._should_update_cache(request, response):
         # We don't need to update the cache, just return.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     patch_response_headers(response, timeout)
     if timeout:
         cache_key = learn_cache_key(request,
                                     response,
                                     timeout,
                                     self.key_prefix,
                                     cache=self.cache)
         if hasattr(response, 'render') and callable(response.render):
             response.add_post_render_callback(
                 lambda r: self.cache.set(cache_key, r, timeout))
         else:
             self.cache.set(cache_key, response, timeout)
     return response
Exemple #8
0
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not hasattr(
             request,
             '_cache_update_cache') or not request._cache_update_cache:
         # We don't need to update the cache, just return.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     patch_response_headers(response, timeout)
     if timeout:
         cache_key = learn_cache_key(request,
                                     response,
                                     timeout,
                                     self.key_prefix,
                                     cache=self.cache)
         self.cache.set(cache_key, response, timeout)
     return response
Exemple #9
0
 def test(self):
     request = RequestFactory().get('/')
     response = my_view(request)
     patch_response_headers(response, cache_timeout=3600)
     self.assertEqual(get_max_age(response), 3600)
     expires = response._headers["expires"][1]
     print(expires)
Exemple #10
0
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not self._should_update_cache(request, response):
         # We don't need to update the cache, just return.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     patch_response_headers(response, timeout)
     if timeout:
         cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache)
         if hasattr(response, 'render') and callable(response.render):
             response.add_post_render_callback(
                 lambda r: self.cache.set(cache_key, r, timeout)
             )
         else:
             self.cache.set(cache_key, response, timeout)
     return response
    def wrapped_view(request, *args, **kwargs):

        # Build a cache key using only the view function and the arguments;
        # nothing related to the request or current site.
        view_path = '.'.join((view_func.__module__, view_func.__name__))
        signature = HashableTuple((args, kwargs)).hash
        cache_key = ':'.join((view_path, signature))

        # Retrieve the response from the cache, or generate a new one.
        if getattr(request, '_purging', False):
            response = None
        else:
            response = cache.get(cache_key)
        if response is None:
            response = view_func(request, *args, **kwargs)
            max_age = get_max_age(response)
            if max_age is not None:
                cache.set(cache_key, response, max_age)
        else:
            response['X-From-Cache'] = True

        # Stop the middleware from caching it too.
        request._cache_update_cache = False

        return response
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response

        if response.streaming or response.status_code != 200:
            return response

        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
            return response

        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        patch_response_headers(response, timeout)
        if timeout:
            cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout)
                )
            else:
                self.cache.set(cache_key, response, timeout)
        return response
Exemple #13
0
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        if response.streaming or response.status_code != 200:
            return response
        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        # patch_response_headers(response, timeout)
        if timeout:
            cache_key = hashlib.md5(
                force_bytes(
                    re.sub(r'^https?://', '',
                           request.build_absolute_uri()))).hexdigest()

            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response.content, timeout)
        return response
Exemple #14
0
    def process_response(self, request, response):
        """
        Rewrite the "Cache-control" and "Expires headers" in the response
        if needed.
        """
        max_ttl = getattr(settings, "MAX_BROWSER_CACHE_TTL", 600)
        if max_ttl:
            try:
                max_ttl = int(max_ttl)
                if max_ttl < 0:
                    raise ValueError(
                        "MAX_BROWSER_CACHE_TTL must be a positive integer")
            except (ValueError, TypeError) as err:
                logger.error(err)
                return response

            max_age = get_max_age(response)
            if max_age is not None and max_age > max_ttl:
                if response.has_header("Expires"):
                    # Remove the Expires response Header because patch_response_headers()
                    # adds it only if it isn't already set
                    del response["Expires"]
                patch_response_headers(response, cache_timeout=max_ttl)

        return response
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache:
         # We don't need to update the cache, just return.
         return response
     if request.method != 'GET':
         # This is a stronger requirement than above. It is needed
         # because of interactions between this middleware and the
         # HTTPMiddleware, which throws the body of a HEAD-request
         # away before this middleware gets a chance to cache it.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     
     if self.patch_headers:
         patch_response_headers(response, timeout)
     
     if timeout:            
         if callable(self.key_prefix):
             key_prefix = self.key_prefix(request)
         else:
             key_prefix = self.key_prefix
         
         cache_key = learn_cache_key(request, response, timeout, key_prefix)
         cache.set(cache_key, response, timeout)
     return response
Exemple #16
0
    def process_response(self, request, response):
        if not self._should_update_cache(request, response):
            return response

        if response.streaming or response.status_code != 200:
            return response

        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
            return response

        if (request.path.startswith('/admin/') or request.path.startswith('/sitemap') or
                request.path[-12:] == '/rss/yandex/' or request.path == 'sidebar.json'):
            return response

        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            return response
        #patch_response_headers(response, 5)
        if timeout:
            cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response, timeout)
        return response
Exemple #17
0
    def process_response(self, request, response):

        # Cache the response if all the required conditions are met.
        # Response must be marked for updating by the
        # ``FetchFromCacheMiddleware`` having a cache get miss, the
        # user must not be authenticated, the HTTP status must be OK
        # and the response mustn't include an expiry age, incicating it
        # shouldn't be cached.
        marked_for_update = getattr(request, "_update_cache", False)
        anon = hasattr(request, "user") and not request.user.is_authenticated()
        valid_status = response.status_code == 200
        timeout = get_max_age(response)
        if timeout is None:
            timeout = settings.CACHE_MIDDLEWARE_SECONDS
        if anon and valid_status and marked_for_update and timeout:
            cache_key = cache_key_prefix(request) + request.get_full_path()
            _cache_set = lambda r: cache_set(cache_key, r.content, timeout)
            if callable(getattr(response, "render", None)):
                response.add_post_render_callback(_cache_set)
            else:
                _cache_set(response)

        # Second phase rendering for non-cached template code and
        # content. Split on the delimiter the ``nevercache`` tag
        # wrapped its contents in, and render only the content
        # enclosed by it, to avoid possible template code injection.
        token = nevercache_token()
        try:
            token = token.encode('utf-8')
        except AttributeError:
            pass
        parts = response.content.split(token)
        content_type = response.get("content-type", "")
        if content_type.startswith("text") and len(parts) > 1:
            # Restore csrf token from cookie - check the response
            # first as it may be being set for the first time.
            csrf_token = None
            try:
                csrf_token = response.cookies[settings.CSRF_COOKIE_NAME].value
            except KeyError:
                try:
                    csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
                except KeyError:
                    pass
            if csrf_token:
                request.META["CSRF_COOKIE"] = csrf_token
            context = RequestContext(request)
            for i, part in enumerate(parts):
                if i % 2:
                    part = Template(part).render(context).encode("utf-8")
                parts[i] = part
            response.content = b"".join(parts)
            response["Content-Length"] = len(response.content)
            if hasattr(request, '_messages'):
                # Required to clear out user messages.
                request._messages.update(response)
        return response
Exemple #18
0
    def process_response(self, request, response):

        # Cache the response if all the required conditions are met.
        # Response must be marked for updating by the
        # ``FetchFromCacheMiddleware`` having a cache get miss, the
        # user must not be authenticated, the HTTP status must be OK
        # and the response mustn't include an expiry age, incicating it
        # shouldn't be cached.
        marked_for_update = getattr(request, "_update_cache", False)
        anon = hasattr(request, "user") and not request.user.is_authenticated()
        valid_status = response.status_code == 200
        timeout = get_max_age(response)
        if timeout is None:
            timeout = settings.CACHE_MIDDLEWARE_SECONDS
        if anon and valid_status and marked_for_update and timeout:
            cache_key = cache_key_prefix(request) + request.get_full_path()
            _cache_set = lambda r: cache_set(cache_key, r.content, timeout)
            if callable(getattr(response, "render", None)):
                response.add_post_render_callback(_cache_set)
            else:
                _cache_set(response)

        # Second phase rendering for non-cached template code and
        # content. Split on the delimiter the ``nevercache`` tag
        # wrapped its contents in, and render only the content
        # enclosed by it, to avoid possible template code injection.
        token = nevercache_token()
        try:
            token = token.encode('utf-8')
        except AttributeError:
            pass
        parts = response.content.split(token)
        content_type = response.get("content-type", "")
        if content_type.startswith("text") and len(parts) > 1:
            # Restore csrf token from cookie - check the response
            # first as it may be being set for the first time.
            csrf_token = None
            try:
                csrf_token = response.cookies[settings.CSRF_COOKIE_NAME].value
            except KeyError:
                try:
                    csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
                except KeyError:
                    pass
            if csrf_token:
                request.META["CSRF_COOKIE"] = csrf_token
            context = RequestContext(request)
            for i, part in enumerate(parts):
                if i % 2:
                    part = Template(part).render(context).encode("utf-8")
                parts[i] = part
            response.content = b"".join(parts)
            response["Content-Length"] = len(response.content)
            if hasattr(request, '_messages'):
                # Required to clear out user messages.
                request._messages.update(response)
        return response
Exemple #19
0
    def process_response(self, request, response):
        if COUNT_UPDATE_CACHE:
            self._count_response(request)

        if getattr(response, "_from_cache", False) == True:
            if COUNT_UPDATE_CACHE:
                self._count_hit()
            logger.debug(
                "response comes from the cache, no need to update the cache")
            return response
        else:
            # used e.g. in unittests
            response._from_cache = False

        if not self.use_cache(request, response):
            if EXTRA_DEBUG:
                logger.debug("Don't put to cache: %s" %
                             request.get_full_path())
            return response

        # get the timeout from the "max-age" section of the "Cache-Control" header
        timeout = get_max_age(response)
        if timeout == None:
            # use default cache_timeout
            timeout = settings.CACHE_MIDDLEWARE_SECONDS
        elif timeout == 0:
            logger.debug("Don't cache this page (timeout == 0)")
            return response

        # Create a new HttpResponse for the cache, so we can skip existing
        # cookies and attributes like response.csrf_processing_done
        response2 = HttpResponse(
            content=response._container,
            status=200,
            content_type=response['Content-Type'],
        )
        if response.has_header("Content-Language"):
            response2['Content-Language'] = response['Content-Language']

        if settings.DEBUG or RUN_WITH_DEV_SERVER or request.META.get(
                'REMOTE_ADDR') in settings.INTERNAL_IPS:
            # Check if we store a {% csrf_token %} into the cache, this should never happen!
            for content in response._container:
                if "csrfmiddlewaretoken" in content:
                    raise AssertionError(
                        "csrf_token would be put into the cache! content: %r" %
                        content)

        # Adds ETag, Last-Modified, Expires and Cache-Control headers
        patch_response_headers(response2, timeout)

        cache_key = get_cache_key(request)
        cache.set(cache_key, response2, timeout)

        logger.debug("Put to cache: %r" % cache_key)
        return response
Exemple #20
0
    def test_invalid_date_params(self):
        with responses.RequestsMock(), silence_logger(name='django.request'):
            response = self.client.get(
                reverse_lazy('performance_data_csv') + '?from=invalid')
            self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
            self.assertIn(
                'Date "invalid" could not be parsed - use YYYY-MM-DD format',
                response.json()['errors'])
            self.assertEqual(0, get_max_age(response))

        with responses.RequestsMock(), silence_logger(name='django.request'):
            response = self.client.get(
                reverse_lazy('performance_data_csv') +
                '?from=2021-01-01&to=invalid')
            self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
            self.assertIn(
                'Date "invalid" could not be parsed - use YYYY-MM-DD format',
                response.json()['errors'])
            self.assertEqual(0, get_max_age(response))
Exemple #21
0
    def process_response(self, request, response):
        if request.COOKIES.get(
                'view_uncached') == 'true' and request.user.is_authenticated:
            return response
        else:
            middleware_cache_tags = self.cache_tags if self.cache_tags else []

            if not self._should_update_cache(request, response):
                return response

            if response.streaming or response.status_code not in (200, 304):
                return response

            # Don't cache responses that set a user-specific (and maybe security
            # sensitive) cookie in response to a cookie-less request.
            if not request.COOKIES and response.cookies and has_vary_header(
                    response, 'Cookie'):
                return response

            # Don't cache a response with 'Cache-Control: private'
            if 'private' in response.get('Cache-Control', ()):
                return response

            # Try to get the timeout from the "max-age" section of the "Cache-
            # Control" header before reverting to using the default cache_timeout
            # length.
            timeout = get_max_age(response)
            if timeout is None:
                timeout = self.cache_timeout
            elif timeout == 0:
                # max-age was set to 0, don't bother caching.
                return response
            patch_response_headers(response, timeout)
            if response.has_header('X-Additional-Cache-Tags'):
                middleware_cache_tags = response.__getitem__(
                    'X-Additional-Cache-Tags').split(",") + self.cache_tags
            if timeout and response.status_code == 200:
                cache_key = learn_cache_key(request,
                                            response,
                                            timeout,
                                            self.key_prefix,
                                            cache=self.cache)
                # add this cache_key to a cache_keys cache with tags

                cache.add_cache_key(request,
                                    cache_key,
                                    tags=middleware_cache_tags)

                if hasattr(response, 'render') and callable(response.render):
                    response.add_post_render_callback(
                        lambda r: self.cache.set(cache_key, r, timeout))
                else:
                    self.cache.set(cache_key, response, timeout)
            return response
Exemple #22
0
    def test_caching(self):
        self.assertTrue(self.response.has_header('Cache-Control'),
                        msg='response has no Cache-Control header')
        self.assertIn('public',
                      self.response['Cache-Control'],
                      msg='response is private')

        expected_max_age = 7 * 24 * 60 * 60  # 7 days in seconds
        self.assertGreaterEqual(get_max_age(self.response),
                                expected_max_age,
                                msg='max-age is less than a week')
    def _assert_not_cached(response):
        """
        Assert that the the max-age header is defined and set to 0,
        or that has a custom vary-on-view header.

        Good decorator to use:
            from django.views.decorators.cache import never_cache

        """

        max_age_header = get_max_age(response)
        assert (max_age_header == 0) or ('X-Vary-On-View' in response)
    def _assert_not_cached(response):
        """
        Assert that the the max-age header is defined and set to 0,
        or that has a custom vary-on-view header.

        Good decorator to use:
            from django.views.decorators.cache import never_cache

        """

        max_age_header = get_max_age(response)
        assert (max_age_header == 0) or ('X-Vary-On-View' in response)
    def _should_cache(self, request, response):
        if response.streaming or response.status_code != 200:
            return False

        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
            return False

        if get_max_age(response) == 0:
            return False

        return True
Exemple #26
0
 def __call__(self, request):
     response = self.get_response(request)
     request_conditions = (request.is_api
                           and request.method in ('GET', 'HEAD')
                           and 'HTTP_AUTHORIZATION' not in request.META
                           and 'disable_caching' not in request.GET)
     response_conditions = (not response.cookies
                            and response.status_code >= 200
                            and response.status_code < 400
                            and get_max_age(response) is None)
     if request_conditions and response_conditions:
         patch_cache_control(response, max_age=settings.API_CACHE_DURATION)
     return response
Exemple #27
0
def process_response(req, res, prefix, cache_time=60 * 60):
    # update the cache using the django's CacheMiddleware
    cache_middleware = CacheMiddleware(cache_timeout=cache_time, key_prefix=prefix)
    response = cache_middleware.process_response(req, res)
    # update some header to prevent wrong client caching
    max_age = get_max_age(response)
    if max_age and max_age < max_age:
        # Remove headers so patch_response works
        for header in ("ETag", "Last-Modified", "Expires"):
            if response.has_header(header):
                del response[header]
        patch_response_headers(response, max_age)
    return response
Exemple #28
0
    def process_response(self, request, response):
        if (request.method in self.allowed_methods and
                response.status_code in self.allowed_statuses and
                request.REQUEST.get('cache') == '1'):
            timeout = get_max_age(response)
            if timeout is None:
                timeout = settings.CACHE_MIDDLEWARE_SECONDS or 0
            if timeout != 0:
                # Only if max-age is 0 should we bother with caching.
                patch_response_headers(response, timeout)
                patch_cache_control(response, must_revalidate=True)

        return response
Exemple #29
0
    def process_response(self, request, response):
        if (request.method in self.allowed_methods and
                response.status_code in self.allowed_statuses and
                request.REQUEST.get('cache') == '1'):
            timeout = get_max_age(response)
            if timeout is None:
                timeout = settings.CACHE_MIDDLEWARE_SECONDS or 0
            if timeout != 0:
                # Only if max-age is 0 should we bother with caching.
                patch_response_headers(response, timeout)
                patch_cache_control(response, must_revalidate=True)

        return response
    def process_response(self, request, response):
        if COUNT_UPDATE_CACHE:
            self._count_response(request)

        if getattr(response, "_from_cache", False) == True:
            if COUNT_UPDATE_CACHE:
                self._count_hit()
            logger.debug("response comes from the cache, no need to update the cache")
            return response
        else:
            # used e.g. in unittests
            response._from_cache = False

        if not self.use_cache(request, response):
            if EXTRA_DEBUG:
                logger.debug("Don't put to cache: %s" % request.get_full_path())
            return response

        # get the timeout from the "max-age" section of the "Cache-Control" header
        timeout = get_max_age(response)
        if timeout == None:
            # use default cache_timeout
            timeout = settings.CACHE_MIDDLEWARE_SECONDS
        elif timeout == 0:
            logger.debug("Don't cache this page (timeout == 0)")
            return response

        # Create a new HttpResponse for the cache, so we can skip existing
        # cookies and attributes like response.csrf_processing_done
        response2 = HttpResponse(
            content=response._container,
            status=200,
            content_type=response['Content-Type'],
        )
        if response.has_header("Content-Language"):
            response2['Content-Language'] = response['Content-Language']

        if settings.DEBUG or RUN_WITH_DEV_SERVER or request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
            # Check if we store a {% csrf_token %} into the cache, this should never happen!
            for content in response._container:
                if "csrfmiddlewaretoken" in content:
                    raise AssertionError("csrf_token would be put into the cache! content: %r" % content)

        # Adds ETag, Last-Modified, Expires and Cache-Control headers
        patch_response_headers(response2, timeout)

        cache_key = get_cache_key(request)
        cache.set(cache_key, response2, timeout)

        logger.debug("Put to cache: %r" % cache_key)
        return response
Exemple #31
0
    def process_response(self, request, response):
        """
        RUS: Возвращает ответ сервера, если пользователь идентифицирован.
        """
        if request.user.is_authenticated():
            return response
        """Sets the cache, if needed."""
        if not self._should_update_cache(request, response):
            return response
        # RUS: Возвращает ответ сервера, если не было обновления кэша.

        if response.streaming or response.status_code != 200:
            return response
        # RUS: Возвращает ответ сервера, если, у атрибута HttpResponse.streaming статус False
        # или код ответа не равен 200.

        # Не кэширует ответы сервера, которые устанавливают специфичные для пользователя (и, возможно,
        # чувствительные к безопасности ) cookie в ответ на запрос без cookie
        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if not request.COOKIES and response.cookies and has_vary_header(
                response, 'Cookie'):
            return response

        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        # Возвращает максимальный возраст из заголовка Cache-Control ответа в виде целого числа (
        # Пытается получить время хранения кэша из заголовка Cache-Control.
        # При его отсутствии, время хранения кэша равно значению по умолчанию,
        # если же установлено равным 0, возвращается некэшированный ответ сервера

        patch_response_headers(response, timeout)
        if timeout:
            cache_key = learn_cache_key(request,
                                        response,
                                        timeout,
                                        self.key_prefix,
                                        cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response, timeout)
        return response
Exemple #32
0
    def process_response(self, request, response):
        """Sets the cache, if needed."""

        # TODO
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response

        # 不是流响应,不是200码
        if response.streaming or response.status_code != 200:
            return response

        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        # 请求没有cookie,但是处理过程中设置了cookie,并且Vary包含了Cookie,直接返回
        # 分析:因为缓存服务器收到请求是没有Cookie的,然后返回的告诉他类似的请求根据Cookie
        # 来判断是否使用缓存,这样,下一个没有Cookie的人访问该URL则会拿到之前的人
        # 的Cookie中的数据
        if not request.COOKIES and response.cookies and has_vary_header(
                response, 'Cookie'):
            return response

        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        # 首先使用response中设置的max_age(根据Cache-Control部分),如果没有设置
        # 则使用setting中的.
        # 分析:setting中的是最后的依据,如果设置过则按照设置过的来
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        # 设置ETag, Last-Modified, Expires 和 Cache-Control的max-age部分,都用于缓存控制
        patch_response_headers(response, timeout)

        if timeout:
            # 拿到cache——key,该方法设置了header_key,返回的是page_key
            cache_key = learn_cache_key(request,
                                        response,
                                        timeout,
                                        self.key_prefix,
                                        cache=self.cache)
            # 如果有render,则设置回调,在render之后缓存.
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response, timeout)
        return response
Exemple #33
0
    def _should_cache(self, request, response):
        if response.streaming or response.status_code != 200:
            return False

        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if not request.COOKIES and response.cookies and has_vary_header(
                response, 'Cookie'):
            return False

        if get_max_age(response) == 0:
            return False

        return True
Exemple #34
0
    def template_response_callback(self, response):
        if self.cache_middleware:
            response = self.cache_middleware.process_response(
                self.request, response)

        # We might want to cache for longer internally than we tell clients
        max_age = get_max_age(response)
        if max_age and self.max_age < max_age:
            # Remove headers so patch_response works
            for header in ('ETag', 'Last-Modified', 'Expires'):
                if response.has_header(header):
                    del response[header]
            patch_response_headers(response, self.max_age)
        return response
Exemple #35
0
    def template_response_callback(self, response):
        if self.cache_middleware:
            response = self.cache_middleware.process_response(
                self.request, response)

        # We might want to cache for longer internally than we tell clients
        max_age = get_max_age(response)
        if max_age and self.max_age < max_age:
            # Remove headers so patch_response works
            for header in ('ETag', 'Last-Modified', 'Expires'):
                if response.has_header(header):
                    del response[header]
            patch_response_headers(response, self.max_age)
        return response
Exemple #36
0
def process_response(req, res, prefix, cache_time=60 * 60):
    # update the cache using the django's CacheMiddleware
    cache_middleware = CacheMiddleware(cache_timeout=cache_time,
                                       key_prefix=prefix)
    response = cache_middleware.process_response(req, res)
    # update some header to prevent wrong client caching
    max_age = get_max_age(response)
    if max_age and max_age < max_age:
        # Remove headers so patch_response works
        for header in ('ETag', 'Last-Modified', 'Expires'):
            if response.has_header(header):
                del response[header]
        patch_response_headers(response, max_age)
    return response
Exemple #37
0
    def process_response(self, request, response):
        # TODO if cache length gets long (like over 10 minutes), set a shorter
        # cache time by default on those.
        #
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3
        # if response.status_code == 302:
        #     return response

        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length inside patch_response_headers.
        timeout = get_max_age(response)
        patch_response_headers(response, timeout)
        return response
Exemple #38
0
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        if (not hasattr(request, '_cache_update_cache')
                or not request._cache_update_cache):
            # We don't need to update the cache, just return.
            return response
        if request.method != 'GET':
            # This is a stronger requirement than above. It is needed
            # because of interactions between this middleware and the
            # HTTPMiddleware, which throws the body of a HEAD-request
            # away before this middleware gets a chance to cache it.
            return response
        if not response.status_code == 200:
            return response
        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response

        if self.patch_headers:
            patch_response_headers(response, timeout)

        if timeout:
            if callable(self.key_prefix):
                key_prefix = self.key_prefix(request)
            else:
                key_prefix = self.key_prefix
            if self.post_process_response:
                response = self.post_process_response(response, request)

            with RequestPath(request, self.only_get_keys,
                             self.forget_get_keys):
                cache_key = learn_cache_key(request, response, timeout,
                                            key_prefix)

                if self.remember_all_urls:
                    self.remember_url(request, cache_key, timeout)

            self.cache.set(cache_key, response, timeout)

        if self.post_process_response_always:
            response = self.post_process_response_always(response, request)

        return response
Exemple #39
0
    def process_response(self, request, response):
        if getattr(response, "_from_cache", False) == True:
            # Current response comes from the cache, no need to update the cache
            return response
        else:
            # used e.g. in unittests
            response._from_cache = False

        if response.status_code != 200: # Don't cache e.g. error pages
            return response

        if not self.use_cache(request):
            #print "Don't put to cache."
            return response

        # get the timeout from the "max-age" section of the "Cache-Control" header
        timeout = get_max_age(response)
        if timeout == None:
            # use default cache_timeout
            timeout = settings.CACHE_MIDDLEWARE_SECONDS
        elif timeout == 0:
            logger.debug("Don't cache this page (timeout == 0)")
            return response

        # Create a new HttpResponse for the cache, so we can skip existing
        # cookies and attributes like response.csrf_processing_done
        response2 = HttpResponse(
            content=response._container,
            status=200,
            content_type=response['Content-Type'],
        )
        if response.has_header("Content-Language"):
            response2['Content-Language'] = response['Content-Language']
        if settings.DEBUG or settings.RUN_WITH_DEV_SERVER:
            # Check if we store a {% csrf_token %} into the cache
            # This can't work ;)
            for content in response._container:
                if "csrfmiddlewaretoken" in content:
                    raise AssertionError("csrf_token would be put into the cache! content: %r" % content)

        # Adds ETag, Last-Modified, Expires and Cache-Control headers
        patch_response_headers(response2, timeout)

        cache_key = self.get_cache_key(request)
        cache.set(cache_key, response2, timeout)

        logger.debug("Put to cache: %r" % cache_key)
        return response
    def _assert_has_headers(response):
        """
        Assert that we have the standard caching headers.

        Good decorators to use:
            from django_cache_middleware.decorators import add_cache_headers
            from django.views.decorators.cache import never_cache

        """

        # A max-age value must be set.
        # A value of 0 is acceptable.
        max_age_header = get_max_age(response)
        assert max_age_header is not None

        # And check for the other ones too.
        for header in ('ETag', 'Last-Modified', 'Expires'):
            assert header in response
    def _assert_has_headers(response):
        """
        Assert that we have the standard caching headers.

        Good decorators to use:
            from django_cache_middleware.decorators import add_cache_headers
            from django.views.decorators.cache import never_cache

        """

        # A max-age value must be set.
        # A value of 0 is acceptable.
        max_age_header = get_max_age(response)
        assert max_age_header is not None

        # And check for the other ones too.
        for header in ('ETag', 'Last-Modified', 'Expires'):
            assert header in response
Exemple #42
0
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response
        if not response.status_code == 200:
            return response
        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout == None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        patch_response_headers(response, timeout)

        user = request.user
        try:
            github_prefix = user.social_auth.get(
                provider='github').extra_data['username']
        except:
            github_prefix = ''
        try:
            bitbucket_prefix = user.social_auth.get(
                provider='bitbucket').extra_data['username']
        except:
            bitbucket_prefix = ''
        custom_prefix = '.'.join((hashlib.md5(github_prefix).hexdigest(),
                                  hashlib.md5(bitbucket_prefix).hexdigest()))

        if timeout:
            cache_key = learn_cache_key(request,
                                        response,
                                        timeout,
                                        custom_prefix,
                                        cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response, timeout)
        return response
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response

        if getattr(response, 'streaming', None) or response.status_code != 200:
            return response
        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        # patch start
        patch_response_headers(response, timeout)
        tags = set()
        if self.tags:
            # Usefull to bind view, args and kwargs to request.
            # See https://bitbucket.org/emacsway/django-ext/src/d8b55d86680e/django_ext/middleware/view_args_to_request.py
            tags = self.tags(request)
        tags = set(tags)
        # Adds tags from request, see templatetag {% cache_add_tags ... %}
        if hasattr(request, 'cache_tagging'):
            tags.update(request.cache_tagging)
        if timeout:
            cache_key = learn_cache_key(request,
                                        response,
                                        tags,
                                        timeout,
                                        self.key_prefix,
                                        cache=self.cache)  # patched
            if hasattr(response, 'render') and isinstance(
                    response.render, collections.Callable):
                response.add_post_render_callback(lambda r: self.cache.set(
                    cache_key, r, tags, timeout)  # patched
                                                  )
            else:
                self.cache.set(cache_key, response, tags, timeout)  # patched
        # patch end
        return response
Exemple #44
0
    def process_response(self, request, response):
        if request.path != '/status':
            cache_entry = Model('cache').facade.get_or_create(
                request.build_absolute_uri())
            cache_entry.requests += 1
            cache_entry.save()

        if not (hasattr(request, '_cache_update_cache')
                and request._cache_update_cache):
            return response

        response['Object-Cache'] = 'MISS'

        if response.streaming or response.status_code not in (200, 304):
            return response

        if not request.COOKIES and response.cookies and has_vary_header(
                response, 'Cookie'):
            return response

        if 'private' in response.get('Cache-Control', ()):
            return response

        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            return response

        patch_response_headers(response, timeout)

        if timeout and response.status_code == 200:
            cache_key = learn_cache_key(request,
                                        response,
                                        timeout,
                                        self.key_prefix,
                                        cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response, timeout)

        return response
Exemple #45
0
    def process_response(self, request, response):
        """Set the cache, if needed."""
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response

        if response.streaming or response.status_code not in (200, 304):
            return response

        # Don't cache responses that set a user-specific (and maybe security
        # sensitive) cookie in response to a cookie-less request.
        if (not request.COOKIES and response.cookies
                and has_vary_header(response, "Cookie")):
            return response

        # Don't cache a response with 'Cache-Control: private'
        if "private" in response.get("Cache-Control", ()):
            return response

        # Page timeout takes precedence over the "max-age" and the default
        # cache timeout.
        timeout = self.page_timeout
        if timeout is None:
            # The timeout from the "max-age" section of the "Cache-Control"
            # header takes precedence over the default cache timeout.
            timeout = get_max_age(response)
            if timeout is None:
                timeout = self.cache_timeout
            elif timeout == 0:
                # max-age was set to 0, don't cache.
                return response
        patch_response_headers(response, timeout)
        if timeout and response.status_code == 200:
            cache_key = learn_cache_key(request,
                                        response,
                                        timeout,
                                        self.key_prefix,
                                        cache=self.cache)
            if hasattr(response, "render") and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout))
            else:
                self.cache.set(cache_key, response, timeout)
        return response
Exemple #46
0
    def process_response(self, request, response):
        if (request.method in self.allowed_methods and
                response.status_code in self.allowed_statuses and
                request.GET.get('cache', '').isdigit()):
            # If there's already a `Cache-Control` header with a `max-age`,
            # use that TTL before falling back to what the client requested.
            timeout = get_max_age(response)
            if timeout is None:
                timeout = int(request.GET['cache'])
                # Never allow clients to choose positive timeouts below
                # settings.CACHE_MIDDLEWARE_SECONDS.
                if timeout > 0 and timeout < settings.CACHE_MIDDLEWARE_SECONDS:
                    timeout = settings.CACHE_MIDDLEWARE_SECONDS
            # Send caching headers, but only timeout is not 0.
            if timeout != 0:
                patch_response_headers(response, timeout)
                patch_cache_control(response, must_revalidate=True)

        return response
Exemple #47
0
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache:
         # We don't need to update the cache, just return.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     patch_response_headers(response, timeout)
     if timeout:
         cache_key = learn_cache_key(request, response, timeout, self.key_prefix)
         self.cache.set(cache_key, response, timeout)
     return response
Exemple #48
0
    def process_response(self, request, response):
        """Sets the cache, if needed."""
        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response
        if not response.status_code == 200:
            return response
        # Try to get the timeout from the "max-age" section of the "Cache-
        # Control" header before reverting to using the default cache_timeout
        # length.
        timeout = get_max_age(response)
        if timeout == None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response
        patch_response_headers(response, timeout)
        
        user = request.user
        try:
            github_prefix = user.social_auth.get(provider='github').extra_data['username']
        except:
            github_prefix = ''
        try:
            bitbucket_prefix=user.social_auth.get(provider='bitbucket').extra_data['username']
        except:
            bitbucket_prefix = ''
        custom_prefix = '.'.join((hashlib.md5(github_prefix).hexdigest(),hashlib.md5(bitbucket_prefix).hexdigest()))

        if timeout:
            cache_key = learn_cache_key(request, response, timeout, custom_prefix, cache=self.cache)
            if hasattr(response, 'render') and callable(response.render):
                response.add_post_render_callback(
                    lambda r: self.cache.set(cache_key, r, timeout)
                )
            else:
                self.cache.set(cache_key, response, timeout)
        return response
 def process_response(self, request, response):
     """Sets the cache, if needed."""
     if not self._should_update_cache(request, response):
         # We don't need to update the cache, just return.
         return response
     if not response.status_code == 200:
         return response
     # Try to get the timeout from the "max-age" section of the "Cache-
     # Control" header before reverting to using the default cache_timeout
     # length.
     timeout = get_max_age(response)
     if timeout == None:
         timeout = self.cache_timeout
     elif timeout == 0:
         # max-age was set to 0, don't bother caching.
         return response
     # patch start
     patch_response_headers(response, timeout)
     tags = set()
     if self.tags:
         # Usefull to bind view, args and kwargs to request.
         # See https://bitbucket.org/emacsway/django-ext/src/d8b55d86680e/django_ext/middleware/view_args_to_request.py
         tags = self.tags(request)
     tags = set(tags)
     # Adds tags from request, see templatetag {% cache_add_tags ... %}
     if hasattr(request, 'cache_tagging'):
         tags.update(request.cache_tagging)
     if timeout:
         cache_key = learn_cache_key(request, response, tags, timeout, self.key_prefix, cache=self.cache)  # patched
         if hasattr(response, 'render') and isinstance(response.render, collections.Callable):
             response.add_post_render_callback(
                 lambda r: self.cache.set(cache_key, r, tags, timeout)  # patched
             )
         else:
             self.cache.set(cache_key, response, tags, timeout)  # patched
     # patch end
     return response
    def process_response(self, request, response):

        if getattr(request, 'response_has_esi', False):
            response['Has-ESI'] = True

        if response.has_header('ETag') and not response['ETag']:
            del response['ETag']

        if not self._should_update_cache(request, response):
            # We don't need to update the cache, just return.
            return response

        if request.method != 'GET':
            return response

        if response.status_code != 200:
            return response

        if not response._is_string:
            # Cannot cache iterable/streamed responses.
            return response

        timeout = get_max_age(response)
        if timeout is None:
            timeout = self.cache_timeout
        elif timeout == 0:
            # max-age was set to 0, don't bother caching.
            return response

        patch_response_headers(response, timeout)

        if timeout:
            cache_key = learn_cache_key(request, response, timeout, self.key_prefix)
            cache_backend.set(cache_key, response, timeout)

        return response
"""
 def process_response(self, request, response):
     if request.path.startswith('/admin/'):
         if get_max_age(response) is None:
             add_never_cache_headers(response)
     return response
Exemple #53
0
    def process_response(self, request, response):

        # Caching is only applicable for text-based, non-streaming
        # responses. We also skip it for non-200 statuses during
        # development, so that stack traces are correctly rendered.
        is_text = response.get("content-type", "").startswith("text")
        valid_status = response.status_code == 200
        streaming = getattr(response, "streaming", False)
        if not is_text or streaming or (settings.DEBUG and not valid_status):
            return response

        # Cache the response if all the required conditions are met.
        # Response must be marked for updating by the
        # ``FetchFromCacheMiddleware`` having a cache get miss, the
        # user must not be authenticated, the HTTP status must be OK
        # and the response mustn't include an expiry age, indicating it
        # shouldn't be cached.
        marked_for_update = getattr(request, "_update_cache", False)
        anon = hasattr(request, "user") and not request.user.is_authenticated()
        timeout = get_max_age(response)
        if timeout is None:
            timeout = settings.CACHE_MIDDLEWARE_SECONDS
        if anon and valid_status and marked_for_update and timeout:
            cache_key = cache_key_prefix(request) + request.get_full_path()
            _cache_set = lambda r: cache_set(cache_key, r.content, timeout)
            if callable(getattr(response, "render", None)):
                response.add_post_render_callback(_cache_set)
            else:
                _cache_set(response)

        # Second phase rendering for non-cached template code and
        # content. Split on the delimiter the ``nevercache`` tag
        # wrapped its contents in, and render only the content
        # enclosed by it, to avoid possible template code injection.
        token = nevercache_token()
        try:
            token = token.encode('utf-8')
        except AttributeError:
            pass
        parts = response.content.split(token)
        # Restore csrf token from cookie - check the response
        # first as it may be being set for the first time.
        csrf_token = None
        try:
            csrf_token = response.cookies[settings.CSRF_COOKIE_NAME].value
        except KeyError:
            try:
                csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
            except KeyError:
                pass
        if csrf_token:
            request.META["CSRF_COOKIE"] = csrf_token
        context = RequestContext(request)
        for i, part in enumerate(parts):
            if i % 2:
                part = Template(part).render(context).encode("utf-8")
            parts[i] = part
        response.content = b"".join(parts)
        response["Content-Length"] = len(response.content)
        if hasattr(request, '_messages'):
            # Required to clear out user messages.
            request._messages.update(response)
        # Response needs to be run-through the CSRF middleware again so
        # that if there was a {% csrf_token %} inside of the nevercache
        # the cookie will be correctly set for the the response
        csrf_mw_name = "django.middleware.csrf.CsrfViewMiddleware"
        if csrf_mw_name in MIDDLEWARE_SETTING:
            response.csrf_processing_done = False
            csrf_mw = CsrfViewMiddleware()
            csrf_mw.process_response(request, response)
        return response
Exemple #54
0
 def _get_timeout(self, response):
     timeout = get_max_age(response)
     if timeout is None:
         timeout = self.cache_timeout
     return timeout
    def process_response(self, request, response):

        # Some built in django views have no caching headers. Ignore them.
        for path in self.ignored_paths:
            if request.path.startswith(path):
                return response

        if response.status_code == 304:
            # Not Modified responses don't need to be checked. They will
            # sometimes have unwanted headers at this point, which Django
            # will remove later on in the base handler.
            return response

        if not self._typical_get_request(request, response):
            # These types of requests/responses should never be cached, and
            # thus should not have caching headers in the response.
            # If they do have cache headers, then they must be "never cache"
            # headers (a max-age of 0).
            if get_max_age(response) not in (0, None):
                raise InvalidHeadersWarning('Only non-secure GET/HEAD requests should have caching headers.')
            else:
                return response

        if response.status_code != 200:
            # We generally only cache responses with a status code of 200,
            # but there are exceptions. As long as the other checks are done
            # then this is OK to let through.
            return response

        # All typical GET requests must have some caching headers defined.
        try:
            self._assert_has_headers(response)
        except AssertionError:
            message = (
                "This URL does not have the required caching headers. "
                "Typical GET requests must return a response with caching headers defined at the view level. "
                "The current headers are: %s"
            )
            header_list = [': '.join(header) for header in response._headers.values()]
            headers = ', '.join(header_list)
            raise InvalidHeadersWarning(message % headers)

        session_was_accessed = hasattr(request, 'session') and request.session.accessed

        if session_was_accessed or has_vary_header(response, 'Cookie'):

            if settings.CACHE_MIDDLEWARE_ANONYMOUS_ONLY:
                # When using this setting, all of the requirements for headers
                # have changed. This is just for Finda Social, which has very
                # different caching rules than the other sites.
                try:
                    self._assert_cache_anonymous_only(request, response)
                except AssertionError, error:
                    raise InvalidHeadersWarning('CACHE_MIDDLEWARE_ANONYMOUS_ONLY is enabled and the following occurred: %s' % error)
                else:
                    return response

            if session_was_accessed:
                message_info = "accessed the user's session (probably by simply accessing request.user)"
            else:
                message_info = "returned a response with the Vary: Cookie header"
            message = "This URL has %s, but the response still has standard caching headers. You can't do both!" % message_info

            # If the session has been accessed and/or the "Vary: Cookie" header
            # exists, then the HTTP headers should specify that the response
            # is not to be cached.
            try:
                self._assert_not_cached(response)
            except AssertionError:
                raise InvalidHeadersWarning(message)