Only cache unauthenticated page views (#117)

This commit is contained in:
Michael Manfre 2022-12-06 00:23:07 -05:00 committed by GitHub
parent b0929214d5
commit b8460b0acd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 23 deletions

View File

@ -1,15 +1,11 @@
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.generic import TemplateView from django.views.generic import TemplateView
from core.decorators import per_identity_cache_page
from users.decorators import identity_required from users.decorators import identity_required
from users.models import FollowStates from users.models import FollowStates
@method_decorator(identity_required, name="dispatch") @method_decorator(identity_required, name="dispatch")
@method_decorator(
per_identity_cache_page("cache_timeout_page_timeline"), name="dispatch"
)
class FollowsPage(TemplateView): class FollowsPage(TemplateView):
""" """
Shows followers/follows. Shows followers/follows.

View File

@ -6,13 +6,15 @@ from django.utils.decorators import method_decorator
from django.views.generic import TemplateView, View from django.views.generic import TemplateView, View
from activities.models import Post, PostInteraction, PostInteractionStates, PostStates from activities.models import Post, PostInteraction, PostInteractionStates, PostStates
from core.decorators import per_identity_cache_page from core.decorators import cache_page_by_ap_json
from core.ld import canonicalise from core.ld import canonicalise
from users.decorators import identity_required from users.decorators import identity_required
from users.shortcuts import by_handle_or_404 from users.shortcuts import by_handle_or_404
@method_decorator(per_identity_cache_page("cache_timeout_page_post"), name="dispatch") @method_decorator(
cache_page_by_ap_json("cache_timeout_page_post", public_only=True), name="dispatch"
)
class Individual(TemplateView): class Individual(TemplateView):
template_name = "activities/post.html" template_name = "activities/post.html"

View File

@ -5,13 +5,12 @@ from django.utils.decorators import method_decorator
from django.views.generic import FormView, ListView from django.views.generic import FormView, ListView
from activities.models import Hashtag, Post, PostInteraction, TimelineEvent from activities.models import Hashtag, Post, PostInteraction, TimelineEvent
from core.decorators import per_identity_cache_page from core.decorators import cache_page
from core.models import Config from core.models import Config
from users.decorators import identity_required from users.decorators import identity_required
@method_decorator(identity_required, name="dispatch") @method_decorator(identity_required, name="dispatch")
@method_decorator(per_identity_cache_page(), name="dispatch")
class Home(FormView): class Home(FormView):
template_name = "activities/home.html" template_name = "activities/home.html"
@ -64,7 +63,7 @@ class Home(FormView):
@method_decorator( @method_decorator(
per_identity_cache_page("cache_timeout_page_timeline"), name="dispatch" cache_page("cache_timeout_page_timeline", public_only=True), name="dispatch"
) )
class Tag(ListView): class Tag(ListView):
@ -102,7 +101,7 @@ class Tag(ListView):
@method_decorator( @method_decorator(
per_identity_cache_page("cache_timeout_page_timeline"), name="dispatch" cache_page("cache_timeout_page_timeline", public_only=True), name="dispatch"
) )
class Local(ListView): class Local(ListView):
@ -130,9 +129,6 @@ class Local(ListView):
@method_decorator(identity_required, name="dispatch") @method_decorator(identity_required, name="dispatch")
@method_decorator(
per_identity_cache_page("cache_timeout_page_timeline"), name="dispatch"
)
class Federated(ListView): class Federated(ListView):
template_name = "activities/federated.html" template_name = "activities/federated.html"

View File

@ -1,34 +1,72 @@
from collections.abc import Callable
from functools import partial, wraps from functools import partial, wraps
from typing import ParamSpecArgs, ParamSpecKwargs
from django.http import HttpRequest
from django.views.decorators.cache import cache_page as dj_cache_page from django.views.decorators.cache import cache_page as dj_cache_page
from core.models import Config from core.models import Config
VaryByFunc = Callable[[HttpRequest, ParamSpecArgs, ParamSpecKwargs], str]
def vary_by_ap_json(request, *args, **kwargs) -> str:
"""
Return a cache usable string token that is different based upon Accept
header.
"""
if request.ap_json:
return "ap_json"
return "not_ap"
def vary_by_identity(request, *args, **kwargs) -> str:
"""
Return a cache usable string token that is different based upon the
request.identity
"""
if request.identity:
return f"ident{request.identity.pk}"
return "identNone"
def cache_page( def cache_page(
timeout: int | str = "cache_timeout_page_default", timeout: int | str = "cache_timeout_page_default",
*, *,
per_identity: bool = False,
key_prefix: str = "", key_prefix: str = "",
public_only: bool = False,
vary_by: VaryByFunc | list[VaryByFunc] | None = None,
): ):
""" """
Decorator for views that caches the page result. Decorator for views that caches the page result.
timeout can either be the number of seconds or the name of a SystemOptions timeout can either be the number of seconds or the name of a SystemOptions
value. value.
If public_only is True, requests with an identity are not cached.
""" """
_timeout = timeout _timeout = timeout
_prefix = key_prefix
if callable(vary_by):
vary_by = [vary_by]
def decorator(function): def decorator(function):
@wraps(function) @wraps(function)
def inner(request, *args, **kwargs): def inner(request, *args, **kwargs):
prefix = key_prefix if public_only:
if per_identity: if request.user.is_authenticated:
identity_id = request.identity.pk if request.identity else "0" return function(request, *args, **kwargs)
prefix = f"{key_prefix or ''}:ident{identity_id}"
prefix = [_prefix]
if isinstance(vary_by, list):
prefix.extend([vfunc(request, *args, **kwargs) for vfunc in vary_by])
prefix = "".join(prefix)
if isinstance(_timeout, str): if isinstance(_timeout, str):
timeout = getattr(Config.system, _timeout) timeout = getattr(Config.system, _timeout)
else: else:
timeout = _timeout timeout = _timeout
return dj_cache_page(timeout=timeout, key_prefix=prefix)(function)( return dj_cache_page(timeout=timeout, key_prefix=prefix)(function)(
request, *args, **kwargs request, *args, **kwargs
) )
@ -38,4 +76,4 @@ def cache_page(
return decorator return decorator
per_identity_cache_page = partial(cache_page, per_identity=True) cache_page_by_ap_json = partial(cache_page, vary_by=[vary_by_ap_json])

View File

@ -18,7 +18,7 @@ def homepage(request):
return LoggedOutHomepage.as_view()(request) return LoggedOutHomepage.as_view()(request)
@method_decorator(cache_page(), name="dispatch") @method_decorator(cache_page(public_only=True), name="dispatch")
class LoggedOutHomepage(TemplateView): class LoggedOutHomepage(TemplateView):
template_name = "index.html" template_name = "index.html"

View File

@ -10,7 +10,7 @@ from django.utils.decorators import method_decorator
from django.views.generic import FormView, ListView, TemplateView, View from django.views.generic import FormView, ListView, TemplateView, View
from activities.models import Post, PostInteraction from activities.models import Post, PostInteraction
from core.decorators import per_identity_cache_page from core.decorators import cache_page, cache_page_by_ap_json
from core.ld import canonicalise from core.ld import canonicalise
from core.models import Config from core.models import Config
from users.decorators import identity_required from users.decorators import identity_required
@ -18,7 +18,7 @@ from users.models import Domain, Follow, FollowStates, Identity, IdentityStates
from users.shortcuts import by_handle_or_404 from users.shortcuts import by_handle_or_404
@method_decorator(per_identity_cache_page(), name="dispatch") @method_decorator(cache_page_by_ap_json(public_only=True), name="dispatch")
class ViewIdentity(ListView): class ViewIdentity(ListView):
""" """
Shows identity profile pages, and also acts as the Actor endpoint when Shows identity profile pages, and also acts as the Actor endpoint when
@ -88,7 +88,7 @@ class ViewIdentity(ListView):
@method_decorator( @method_decorator(
per_identity_cache_page("cache_timeout_identity_feed"), name="__call__" cache_page("cache_timeout_identity_feed", public_only=True), name="__call__"
) )
class IdentityFeed(Feed): class IdentityFeed(Feed):
""" """