Cache Fixes, Django 4.0 Update

This commit is contained in:
Martin Mahner 2021-12-13 11:00:40 +01:00
parent 0291bcd908
commit 49ca2d7631
7 changed files with 49 additions and 47 deletions

View File

@ -1,6 +1,14 @@
Changelog
=========
3.6 (master)
------------
- Added support for Python 3.9.
- Added support for Python 3.10.
- Removed cache headers for all views except 404. Due to that snippets can be
deleted, it's not trivial to have them removed from upstream caches.
3.5 (2020-01-08)
----------------

View File

@ -2,6 +2,9 @@ from django.apps import AppConfig, apps
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from logging import getLogger
log = getLogger(__file__)
class dpasteAppConfig(AppConfig):
name = "dpaste"
@ -610,12 +613,8 @@ class dpasteAppConfig(AppConfig):
# ('zephir', 'Zephir')
]
# Whether to send out cache headers (Max-Age, Never-Cache, etc.).
CACHE_HEADER = True
# Defines how long pages are cached by upstream Proxies (Max-Age Header).
# This does not affect caching of snippets, their max-age limit is set
# to the expire date.
# Cache timeout for 404 and static pages. Snippets don't have an explicit
# Cache timeout set to avoid caching in upstream proxies.
CACHE_TIMEOUT = 60 * 10
@staticmethod

View File

@ -1,11 +1,11 @@
from django.conf.urls import include, url
from django.urls import include, re_path
urlpatterns = [
url(r"^", include("dpaste.urls.dpaste_api")),
url(r"^", include("dpaste.urls.dpaste")),
url(r"^i18n/", include("django.conf.urls.i18n")),
re_path(r"^", include("dpaste.urls.dpaste_api")),
re_path(r"^", include("dpaste.urls.dpaste")),
re_path(r"^i18n/", include("django.conf.urls.i18n")),
]
# Custom error handlers which load `dpaste/<code>.html` instead of `<code>.html`
handler404 = "dpaste.views.page_not_found"
handler500 = "dpaste.views.server_error"
handler404 = "dpaste.views.handler404"
handler500 = "dpaste.views.handler500"

View File

@ -1,6 +1,6 @@
from django.apps import apps
from django.conf import settings
from django.conf.urls import url
from django.urls import re_path
from django.views.decorators.cache import cache_control
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import TemplateView
@ -11,8 +11,8 @@ L = getattr(settings, "DPASTE_SLUG_LENGTH", 4)
config = apps.get_app_config("dpaste")
urlpatterns = [
url(r"^$", views.SnippetView.as_view(), name="snippet_new"),
url(
re_path(r"^$", views.SnippetView.as_view(), name="snippet_new"),
re_path(
r"^about/$",
cache_control(max_age=config.CACHE_TIMEOUT)(
TemplateView.as_view(
@ -22,18 +22,18 @@ urlpatterns = [
),
name="dpaste_about",
),
url(r"^history/$", views.SnippetHistory.as_view(), name="snippet_history"),
url(
re_path(r"^history/$", views.SnippetHistory.as_view(), name="snippet_history"),
re_path(
r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/?$" % L,
views.SnippetDetailView.as_view(),
name="snippet_details",
),
url(
re_path(
r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/raw/?$" % L,
views.SnippetRawView.as_view(),
name="snippet_details_raw",
),
url(
re_path(
r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/slim/?$" % L,
xframe_options_exempt(
views.SnippetDetailView.as_view(template_name="dpaste/details_slim.html")

View File

@ -1,8 +1,8 @@
from django.conf.urls import url
from django.urls import re_path
from django.views.decorators.csrf import csrf_exempt
from ..views import APIView
urlpatterns = [
url(r"^api/$", csrf_exempt(APIView.as_view()), name="dpaste_api_create_snippet",)
re_path(r"^api/$", csrf_exempt(APIView.as_view()), name="dpaste_api_create_snippet",)
]

View File

@ -1,5 +1,6 @@
import datetime
import difflib
import ipaddress
import json
from django.apps import apps
@ -14,19 +15,22 @@ from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.utils import timezone
from django.utils.cache import add_never_cache_headers, patch_cache_control
from django.utils.http import http_date
from django.utils.translation import ugettext
from django.utils.translation import gettext
from django.views.generic import FormView
from django.views.generic.base import TemplateView, View
from django.views.generic.detail import DetailView
from pygments.lexers import get_lexer_for_filename
from pygments.util import ClassNotFound
from ratelimit.decorators import ratelimit
from ratelimit.exceptions import Ratelimited
from dpaste import highlight
from dpaste.forms import SnippetForm, get_expire_values
from dpaste.highlight import PygmentsHighlighter
from dpaste.models import Snippet
from django.conf import settings
config = apps.get_app_config("dpaste")
@ -45,8 +49,6 @@ class SnippetView(FormView):
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
if config.CACHE_HEADER:
patch_cache_control(response, max_age=config.CACHE_TIMEOUT)
return response
def get_form_kwargs(self):
@ -111,18 +113,7 @@ class SnippetDetailView(DetailView, FormView):
snippet.view_count += 1
snippet.save(update_fields=["view_count"])
response = super().get(request, *args, **kwargs)
# Set the Max-Age header up until the snippet would expire
if config.CACHE_HEADER:
if snippet.expire_type == Snippet.EXPIRE_KEEP:
patch_cache_control(response, max_age=config.CACHE_TIMEOUT)
if snippet.expire_type == Snippet.EXPIRE_ONETIME:
add_never_cache_headers(response)
if snippet.expire_type == Snippet.EXPIRE_TIME and snippet.expires:
response["Expires"] = http_date(snippet.expires.timestamp())
return response
return super().get(request, *args, **kwargs)
def get_initial(self):
snippet = self.get_object()
@ -153,8 +144,8 @@ class SnippetDetailView(DetailView, FormView):
d = difflib.unified_diff(
snippet.parent.content.splitlines(),
snippet.content.splitlines(),
ugettext("Previous Snippet"),
ugettext("Current Snippet"),
gettext("Previous Snippet"),
gettext("Current Snippet"),
n=1,
)
diff_code = "\n".join(d).strip()
@ -188,7 +179,7 @@ class SnippetRawView(SnippetDetailView):
def dispatch(self, request, *args, **kwargs):
if not config.RAW_MODE_ENABLED:
return HttpResponseForbidden(
ugettext("This dpaste installation has Raw view mode disabled.")
gettext("This dpaste installation has Raw view mode disabled.")
)
return super().dispatch(request, *args, **kwargs)
@ -332,7 +323,10 @@ class APIView(View):
expire_type = Snippet.EXPIRE_TIME
snippet = Snippet.objects.create(
content=content, lexer=lexer, expires=expires, expire_type=expire_type,
content=content,
lexer=lexer,
expires=expires,
expire_type=expire_type,
)
# Custom formatter for the API response
@ -349,17 +343,15 @@ class APIView(View):
# handle them here.
# -----------------------------------------------------------------------------
def page_not_found(request, exception=None, template_name="dpaste/404.html"):
def handler404(request, exception=None, template_name="dpaste/404.html"):
context = {}
context.update(config.extra_template_context)
response = render(request, template_name, context, status=404)
if config.CACHE_HEADER:
patch_cache_control(response, max_age=config.CACHE_TIMEOUT)
patch_cache_control(response, max_age=config.CACHE_TIMEOUT)
return response
def server_error(request, template_name="dpaste/500.html"):
def handler500(request, template_name="dpaste/500.html"):
context = {}
context.update(config.extra_template_context)
response = render(request, template_name, context, status=500)

View File

@ -4,7 +4,8 @@ skip_missing_interpreters=True
envlist=
readme
coverage_setup
py{36,37,38}-django-{22,30,31}
py{36,37,38,39,310}-django-{22,30,31,32}
py{38,39,310}-django-{40}
coverage_report
[testenv]
@ -18,6 +19,8 @@ deps=
django-22: django>=2.2,<3.0
django-30: django>=3.0,<3.1
django-31: django>=3.1,<3.2
django-32: django>=3.2,<4.0
django-40: django>=4.0,<4.1
[testenv:coverage_setup]
skip_install = True