Implement CDN cache backends

This commit is contained in:
Quantum 2022-01-24 02:43:49 -05:00
parent 0a6c2a7cd0
commit 9a9f0d4cab
7 changed files with 67 additions and 4 deletions

View file

@ -17,17 +17,17 @@ class LinkAdmin(admin.ModelAdmin):
search_fields = ('short', 'long')
@admin.display(ordering='short', description=_('short slug'))
def short_slug(self, obj):
def short_slug(self, obj: Link):
return obj.short or '/'
@admin.display(ordering='long', description=_('long URL'))
def long_url(self, obj):
def long_url(self, obj: Link):
return format_html('<a href="{0}">{1}</a>', obj.long, truncatechars(obj.long, 64))
@admin.display(description=_('link'))
def short_url(self, obj):
def short_url(self, obj: Link):
if settings.QLINKS_CANONICAL:
return format_html('<a href="{0}{1}">{2}</a>', settings.QLINKS_CANONICAL, obj.short, gettext('Link'))
return format_html('<a href="{0}">{1}</a>', obj.short_url, gettext('Link'))
def save_model(self, request, obj: Link, form, change):
obj.created_by = request.user
@ -35,6 +35,11 @@ class LinkAdmin(admin.ModelAdmin):
obj.is_working = check_url(obj.long)
obj.last_check = timezone.now()
super().save_model(request, obj, form, change)
obj.purge_cdn()
def delete_model(self, request, obj: Link):
super().delete_model(request, obj)
obj.purge_cdn()
admin.site.register(Link, LinkAdmin)

View file

@ -0,0 +1,12 @@
from typing import Optional
from django.conf import settings
from django.utils.module_loading import import_string
from qlinks.cdn_cache.base import BaseCDNCache
cdn_cache: Optional[BaseCDNCache]
if settings.QLINKS_CDN_CACHE:
cdn_cache = import_string(settings.QLINKS_CDN_CACHE)()
else:
cdn_cache = None

9
qlinks/cdn_cache/base.py Normal file
View file

@ -0,0 +1,9 @@
import abc
class BaseCDNCache(abc.ABC):
@abc.abstractmethod
def __init__(self): ...
@abc.abstractmethod
def purge(self, url: str) -> None: ...

View file

@ -0,0 +1,18 @@
from CloudFlare import CloudFlare
from django.conf import settings
from qlinks.cdn_cache import BaseCDNCache
class CloudflareCDNCache(BaseCDNCache):
cf: CloudFlare
zone: str
def __init__(self):
self.cf = CloudFlare(token=getattr(settings, 'QLINKS_CDN_CLOUDFLARE_API_TOKEN', None))
self.zone = settings.QLINKS_CDN_CLOUDFLARE_ZONE_ID
def purge(self, url: str) -> None:
self.cf.zones.purge_cache.post(self.zone, data={
'files': [url],
})

View file

@ -1,8 +1,12 @@
from functools import cached_property
from django.conf import settings
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from qlinks.cdn_cache import cdn_cache
class Link(models.Model):
short = models.SlugField(max_length=64, verbose_name=_('short link slug'), unique=True, blank=True,
@ -18,3 +22,11 @@ class Link(models.Model):
def __str__(self):
return self.short or '/'
@cached_property
def short_url(self):
return settings.QLINKS_CANONICAL + self.short
def purge_cdn(self):
if cdn_cache:
cdn_cache.purge(self.short_url)

View file

@ -86,3 +86,4 @@ QLINKS_CANONICAL = None
QLINKS_SITE_HEADER = 'QLinks Admin'
QLINKS_SITE_TITLE = 'QLinks Admin'
QLINKS_INDEX_TITLE = 'Welcome to the QLinks admin interface!'
QLINKS_CDN_CACHE = None

View file

@ -27,3 +27,9 @@ QLINKS_ADMIN_HOST = r'admin'
# Set to link prefix for short links, e.g. 'https://short.example.com/'
QLINKS_CANONICAL = None
# If you are using a CDN, you can optionally configure it to cache all the
# redirects, and then use a CDN cache backend to purge the cache.
# QLINKS_CDN_CACHE = 'qlinks.cdn_cache.cloudflare_cache.CloudflareCDNCache'
# QLINKS_CDN_CLOUDFLARE_API_TOKEN = ...
# QLINKS_CDN_CLOUDFLARE_API_ZONE_ID = ...