Changeset - 1cfe805689a2
[Not reviewed]
0 3 0
Ben Sturmfels (bsturmfels) - 2 months ago 2024-03-20 04:45:46
ben@sturm.com.au
Handle trailing slashes in static content
3 files changed with 12 insertions and 6 deletions:
0 comments (0 inline, 0 general)
TODO.md
Show inline comments
 
# 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
 
* 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
 
* add tests for main pages returning 200
 

	
 

	
 
# 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`
 
  with `settings/prod.py` and move `SECRET_KEY` to an environment variable
 
* migrate to Django 4.2 LTS
 
* review `apache2` directory - may be unused
 
* add deployment script that runs migrations and collects static files
 
* switch `ParameterValidator` to use `SECRET_KEY` if possible to minimize
 
  non-standard settings
 
* install staticfiles app
conservancy/urls.py
Show inline comments
...
 
@@ -36,25 +36,25 @@ urlpatterns = [
 
    path('feeds/omnibus/', feeds.OmnibusFeed()),
 
    path('feeds/', feeds.view),
 
    path('news/', include('conservancy.news.urls')),
 
    path('blog/', include('conservancy.blog.urls')),
 
    # formerly static templated things... (dirs with templates)
 
    re_path(r'^about/', static_views.index),
 
    re_path(r'^activities/', static_views.index),
 
    re_path(r'^donate/', static_views.index),
 
    re_path(r'^copyleft-compliance/', static_views.index, {'fundraiser_sought': 'vmware-match-0'}),
 
    re_path(r'^learn/', static_views.index),
 
    re_path(r'^press/', 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'}),
 
    path('contractpatch/', include('conservancy.contractpatch.urls')),
 
    re_path(r'^overview/', static_views.index),
 
    re_path(r'^privacy-policy/', static_views.index),
 
    path('sustainer/', include('conservancy.supporter.urls')),
 
    re_path(r'^coming-soon.html', static_views.index),
 
    path('fundraiser_data/', fundgoal_views.view),
 
    path('assignment/', include('conservancy.assignment.urls')),
 
    path('fossy/', static_views.index),
 
    path('fossy/', include('conservancy.fossy.urls')),
 
    path('casts/the-corresponding-source/', include('conservancy.podjango.urls')),
 
    path('usethesource/', include('conservancy.usethesource.urls')),
conservancy/views.py
Show inline comments
 
import mimetypes
 

	
 
from django.conf import settings
 
from django.http import Http404
 
from django.http import FileResponse
 
from django.http import FileResponse, Http404, HttpResponseRedirect
 
from django.template.response import TemplateResponse
 

	
 
from .local_context_processors import fundgoal_lookup
 

	
 
def index(request, *args, **kwargs):
 
    """Faux CMS: bulk website content stored in templates and document files.
 

	
 
    Rationale: Many websites have a CMS and store the majority of their website
 
    content in a relational database eg. WordPress or Wagtail. That's useful
 
    because various people can easily be given access to edit the website. The
 
    downside is that is application complexity - the management of who change
 
    what, when it changed and what changed becomes an application concern. At
...
 
@@ -26,25 +25,28 @@ def index(request, *args, **kwargs):
 
    files - it looks at the URL and tries to find a matching file on the
 
    filesystem. If it finds a template, it renders it via Django's template
 
    infrastructure. If it finds a file but it's not a template, it will serve
 
    the file as-is.
 
    """
 
    # The name "static" has no connection to Django staticfiles.
 
    base_path = settings.BASE_DIR / 'static'
 
    path = request.path.lstrip('/')
 
    if path.endswith('/'):
 
        path += 'index.html'
 
    full_path = (base_path / path).resolve()
 
    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()
 
    is_template = mimetypes.guess_type(full_path)[0] == 'text/html'
 
    if not is_template:
 
        return FileResponse(open(full_path, 'rb'))
 
    else:
 
        context = kwargs.copy()
 
        try:
 
            context['fundgoal'] = fundgoal_lookup(kwargs['fundraiser_sought'])
 
        except KeyError:
 
            pass
 
        # Maybe this should open() the template file directly so that these
 
        # don't have to be included in the global template TEMPLATES.DIRS?
0 comments (0 inline, 0 general)