diff --git a/swh/web/common/middlewares.py b/swh/web/common/middlewares.py --- a/swh/web/common/middlewares.py +++ b/swh/web/common/middlewares.py @@ -3,6 +3,8 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information +from django.middleware.cache import FetchFromCacheMiddleware + from htmlmin import minify import sentry_sdk @@ -69,3 +71,21 @@ if 'RateLimit-Reset' in request.META: resp['X-RateLimit-Reset'] = request.META['RateLimit-Reset'] return resp + + +class AnonymousFetchFromCacheMiddleware(FetchFromCacheMiddleware): + """ + Middleware extending django.middleware.cache.FetchFromCacheMiddleware + behavior by do not caching requests for authenticated users. + """ + def __init__(self, get_response=None): + super().__init__(get_response) + + def process_request(self, request): + # Don't cache requests from authenticated users. + if request.method in ('GET', 'HEAD') and request.user.is_authenticated: + request._cache_update_cache = False + request._not_cached = True + return None + + return super().process_request(request) diff --git a/swh/web/settings/production.py b/swh/web/settings/production.py --- a/swh/web/settings/production.py +++ b/swh/web/settings/production.py @@ -19,7 +19,7 @@ MIDDLEWARE.insert(0, 'django.middleware.cache.UpdateCacheMiddleware') MIDDLEWARE += ['swh.web.common.middlewares.HtmlMinifyMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware'] + 'swh.web.common.middlewares.AnonymousFetchFromCacheMiddleware'] if swh_web_config.get('throttling', {}).get('cache_uri'): CACHES.update({ diff --git a/swh/web/tests/common/test_middlewares.py b/swh/web/tests/common/test_middlewares.py new file mode 100644 --- /dev/null +++ b/swh/web/tests/common/test_middlewares.py @@ -0,0 +1,36 @@ +# Copyright (C) 2020 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU Affero General Public License version 3, or any later version +# See top-level LICENSE file for more information + +from django.contrib.auth.models import User +from django.test import modify_settings + +import pytest + +from swh.web.common.utils import reverse + + +@pytest.mark.django_db +def test_auth_user_no_per_site_caching_middleware(client): + patched_settings = modify_settings(MIDDLEWARE={ + 'append': ('swh.web.common.middlewares.' + 'AnonymousFetchFromCacheMiddleware'), + 'prepend': 'django.middleware.cache.UpdateCacheMiddleware', + }) + patched_settings.enable() + + url = reverse('swh-web-homepage') + client.get(url) + resp = client.get(url) + + assert not hasattr(resp.wsgi_request, '_not_cached') + + user = User.objects.create_user( + username='testuser', password='password') + client.force_login(user) + resp = client.get(url) + + assert hasattr(resp.wsgi_request, '_not_cached') + + patched_settings.disable()