Skip to content

Allow 404 pages to be cached #397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cloudflare/workers.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ const REPLACE_STRIPPED_QUERYSTRING_ON_REDIRECT_LOCATION = false;
// Disabled by default, but highly recommended
const STRIP_VALUELESS_QUERYSTRING_KEYS = false;

// Only these status codes should be considered cacheable
// Only these status codes should be considered cacheable.
// (from https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4)
const CACHABLE_HTTP_STATUS_CODES = [200, 203, 206, 300, 301, 410];
// 404 is added to reduce server load on spammed requests.
const CACHABLE_HTTP_STATUS_CODES = [200, 203, 206, 300, 301, 404, 410];

addEventListener('fetch', (event) => {
event.respondWith(main(event));
Expand Down
18 changes: 18 additions & 0 deletions tbx/core/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,21 @@ def test_setting_theme_on_one_site_sets_it_on_multiple_sites(self):
# check theme is set on new site
resp = self.client.get(f"http://{new_site.hostname}/")
self.assertEqual(resp.context["MODE"], mode)


class PageNotFoundTestCase(TestCase):
def test_page_not_found(self) -> None:
response = self.client.get("/does-not-exist/")
self.assertEqual(response.status_code, 404)
self.assertEqual(
response.headers["Cache-Control"],
"s-maxage=600, stale-while-revalidate=60, public",
)

def test_test_404(self) -> None:
response = self.client.get("/test404/")
self.assertEqual(response.status_code, 404)
self.assertEqual(
response.headers["Cache-Control"],
"s-maxage=600, stale-while-revalidate=60, public",
)
9 changes: 8 additions & 1 deletion tbx/core/utils/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from django.views import defaults
from django.views.decorators.cache import cache_control, never_cache

from tbx.core.utils.cache import get_default_cache_control_kwargs

def page_not_found(request, exception, template_name="patterns/pages/errors/404.html"):

@cache_control(**(get_default_cache_control_kwargs() | {"s_maxage": 600}))
def page_not_found(
request, exception=None, template_name="patterns/pages/errors/404.html"
):
return defaults.page_not_found(request, exception, template_name)


@never_cache
def server_error(request, template_name="patterns/pages/errors/500.html"):
return defaults.server_error(request, template_name)
7 changes: 4 additions & 3 deletions tbx/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

# Basic settings
DEBUG = False
TEST = False

APP_NAME = env.get("APP_NAME", "torchbox")

Expand Down Expand Up @@ -549,13 +550,13 @@
# Set s-max-age header that is used by reverse proxy/front end cache. See
# urls.py
with contextlib.suppress(ValueError):
CACHE_CONTROL_S_MAXAGE = int(env.get("CACHE_CONTROL_S_MAXAGE", 600))
CACHE_CONTROL_S_MAXAGE = int(env.get("CACHE_CONTROL_S_MAXAGE", 14400))


# Give front-end cache 30 second to revalidate the cache to avoid hitting the
# Give front-end cache 60 second to revalidate the cache to avoid hitting the
# backend. See urls.py
CACHE_CONTROL_STALE_WHILE_REVALIDATE = int(
env.get("CACHE_CONTROL_STALE_WHILE_REVALIDATE", 30)
env.get("CACHE_CONTROL_STALE_WHILE_REVALIDATE", 60)
)

# Embeds
Expand Down
2 changes: 2 additions & 0 deletions tbx/settings/test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from .base import * # noqa: F403


TEST = True

# #############
# General

Expand Down
20 changes: 7 additions & 13 deletions tbx/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
get_default_cache_control_decorator,
get_default_cache_control_method_decorator,
)
from tbx.core.utils.views import page_not_found, server_error
from tbx.core.views import robots, switch_mode


Expand All @@ -32,26 +33,19 @@
]


if settings.DEBUG:
if settings.DEBUG or settings.TEST:
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.generic import TemplateView

# Serve static and media files from development server
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

# Add views for testing 404 and 500 templates
urlpatterns += [
private_urlpatterns += [
# Add views for testing 404 and 500 templates
path(
"test404/",
TemplateView.as_view(template_name="patterns/pages/errors/404.html"),
),
path(
"test500/",
TemplateView.as_view(template_name="patterns/pages/errors/500.html"),
),
path("test404/", page_not_found),
path("test500/", server_error),
]

# Django Debug Toolbar
Expand Down Expand Up @@ -104,5 +98,5 @@
)

# Error handlers
handler404 = "tbx.core.utils.views.page_not_found"
handler500 = "tbx.core.utils.views.server_error"
handler404 = page_not_found
handler500 = server_error