Handle trailing slashes in static content

This commit is contained in:
Ben Sturmfels 2024-03-20 15:45:46 +11:00
parent 5fa226284b
commit 1cfe805689
Signed by: bsturmfels
GPG key ID: 023C05E2C9C068F0
3 changed files with 12 additions and 6 deletions

View file

@ -1,15 +1,19 @@
# To-do # To-do
* split the template/content files out from `conservancy/static` into their own
`content` directory (avoid mixing static and non-static content)
* ask Denver about why so many license files * ask Denver about why so many license files
* serve a 400 in Apache for a hostname we don't explicitly support * serve a 400 in Apache for a hostname we don't explicitly support
* use `<detail>` elements for supporter page hidden sections, rather than complex jQuery - or consider Alpine.js * use `<detail>` elements for supporter page hidden sections, rather than
complex jQuery - or consider Alpine.js
* replace `internalNavigate` with inline flexbox layout * replace `internalNavigate` with inline flexbox layout
* add tests for main pages returning 200 * add tests for main pages returning 200
# Done # Done
* remove `ForceCanonicalHostnameMiddleware` by ensuring canonical redirect and HTTPS redirect is done by Apache * remove `ForceCanonicalHostnameMiddleware` by ensuring canonical redirect and
HTTPS redirect is done by Apache
* standardise settings to replace `settings.py` and `djangocommonsettings.py` * standardise settings to replace `settings.py` and `djangocommonsettings.py`
with `settings/prod.py` and move `SECRET_KEY` to an environment variable with `settings/prod.py` and move `SECRET_KEY` to an environment variable
* migrate to Django 4.2 LTS * migrate to Django 4.2 LTS

View file

@ -45,7 +45,7 @@ urlpatterns = [
re_path(r'^learn/', static_views.index), re_path(r'^learn/', static_views.index),
re_path(r'^press/', static_views.index), re_path(r'^press/', static_views.index),
re_path(r'^projects/', static_views.index), re_path(r'^projects/', static_views.index),
re_path(r'^GiveUpGitHub', static_views.index), re_path(r'^GiveUpGitHub/', static_views.index),
re_path(r'^npoacct/', static_views.index, {'fundraiser_sought': 'npoacct'}), re_path(r'^npoacct/', static_views.index, {'fundraiser_sought': 'npoacct'}),
path('contractpatch/', include('conservancy.contractpatch.urls')), path('contractpatch/', include('conservancy.contractpatch.urls')),
re_path(r'^overview/', static_views.index), re_path(r'^overview/', static_views.index),

View file

@ -1,8 +1,7 @@
import mimetypes import mimetypes
from django.conf import settings from django.conf import settings
from django.http import Http404 from django.http import FileResponse, Http404, HttpResponseRedirect
from django.http import FileResponse
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from .local_context_processors import fundgoal_lookup from .local_context_processors import fundgoal_lookup
@ -35,7 +34,10 @@ def index(request, *args, **kwargs):
path += 'index.html' path += 'index.html'
full_path = (base_path / path).resolve() full_path = (base_path / path).resolve()
safe_from_path_traversal = full_path.is_relative_to(base_path) safe_from_path_traversal = full_path.is_relative_to(base_path)
if not full_path.exists() or not safe_from_path_traversal: if full_path.is_dir():
# Should have been accessed with a trailing slash.
return HttpResponseRedirect(request.path + '/')
elif not full_path.exists() or not safe_from_path_traversal:
raise Http404() raise Http404()
is_template = mimetypes.guess_type(full_path)[0] == 'text/html' is_template = mimetypes.guess_type(full_path)[0] == 'text/html'
if not is_template: if not is_template: