Delegate management of canonical URLs to Apache
This middleware is mostly redundant: * redirecting to canonical URLs can be done more simply in Apache * appending a forward slash is a default in CommonMiddleware now * we're no longer using Squid cache May need to update Apache to strip/redirect trailing "index.html".
This commit is contained in:
parent
c795e1799c
commit
5fa226284b
8 changed files with 4 additions and 85 deletions
3
TODO.md
3
TODO.md
|
@ -1,6 +1,6 @@
|
||||||
# To-do
|
# To-do
|
||||||
|
|
||||||
* remove `ForceCanonicalHostnameMiddleware` by ensuring canonical redirect and HTTPS redirect is done by Apache
|
* 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
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
|
|
||||||
|
* 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
|
||||||
|
|
|
@ -114,11 +114,8 @@ def query(request):
|
||||||
|
|
||||||
def relative_redirect(request, path):
|
def relative_redirect(request, path):
|
||||||
from django import http
|
from django import http
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
host = request.get_host()
|
host = request.get_host()
|
||||||
if settings.FORCE_CANONICAL_HOSTNAME:
|
|
||||||
host = settings.FORCE_CANONICAL_HOSTNAME
|
|
||||||
|
|
||||||
url = "{}://{}{}".format(request.is_secure() and 'https' or 'http', host, path)
|
url = "{}://{}{}".format(request.is_secure() and 'https' or 'http', host, path)
|
||||||
return http.HttpResponseRedirect(url)
|
return http.HttpResponseRedirect(url)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from datetime import datetime as DateTime
|
from datetime import datetime as DateTime
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from .fundgoal.models import FundraisingGoal
|
from .fundgoal.models import FundraisingGoal
|
||||||
|
|
||||||
SITE_FUNDGOAL = 'cy2023-end-year-match'
|
SITE_FUNDGOAL = 'cy2023-end-year-match'
|
||||||
|
@ -19,10 +17,5 @@ def sitefundraiser(request):
|
||||||
'sitefundgoal': fundgoal_lookup(SITE_FUNDGOAL),
|
'sitefundgoal': fundgoal_lookup(SITE_FUNDGOAL),
|
||||||
}
|
}
|
||||||
|
|
||||||
if settings.FORCE_CANONICAL_HOSTNAME:
|
def host_url(request):
|
||||||
_HOST_URL_VAR = {'host_url': 'https://' + settings.FORCE_CANONICAL_HOSTNAME}
|
return {'host_url': request.build_absolute_uri('/').rstrip('/')}
|
||||||
def host_url(request):
|
|
||||||
return _HOST_URL_VAR
|
|
||||||
else:
|
|
||||||
def host_url(request):
|
|
||||||
return {'host_url': request.build_absolute_uri('/').rstrip('/')}
|
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
from django import http
|
|
||||||
from django.conf import settings
|
|
||||||
from django.utils.cache import patch_response_headers
|
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
|
||||||
|
|
||||||
|
|
||||||
class ForceCanonicalHostnameMiddleware(MiddlewareMixin):
|
|
||||||
# MiddlewareMixin provides compatiiblity for Django 1.10 style middleware.
|
|
||||||
|
|
||||||
def process_request(self, request):
|
|
||||||
"""Modified common middleware for Conservancy site
|
|
||||||
|
|
||||||
* Performs redirects to strip trailing "index.html"
|
|
||||||
* performs redirects based on APPEND_SLASH
|
|
||||||
* performs redirects based on site-specific REDIRECT_TABLE
|
|
||||||
* adds cache headers to provide hints to squid
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Never allow connection to the /admin part of the site without SSL
|
|
||||||
if (not request.is_secure) and request.path.startswith('/admin'):
|
|
||||||
url = 'https://sfconservancy.org%s' % request.path
|
|
||||||
return http.HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
# Check for a redirect based on settings.APPEND_SLASH
|
|
||||||
host = request.get_host()
|
|
||||||
old_url = [host, request.path]
|
|
||||||
new_url = old_url[:]
|
|
||||||
# Append a slash if append_slash is set and the URL doesn't have a
|
|
||||||
# trailing slash or a file extension.
|
|
||||||
if settings.APPEND_SLASH and (old_url[1][-1] != '/') and ('.' not in old_url[1].split('/')[-1]):
|
|
||||||
new_url[1] = new_url[1] + '/'
|
|
||||||
if settings.DEBUG and request.method == 'POST':
|
|
||||||
raise(RuntimeError, "You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to {}{} (note the trailing slash), or set APPEND_SLASH=False in your Django settings.".format(new_url[0], new_url[1]))
|
|
||||||
# Strip trailing index.html
|
|
||||||
if new_url[1].endswith('/index.html'):
|
|
||||||
new_url[1] = new_url[1][:new_url[1].rfind('index.html')]
|
|
||||||
# Consult redirect table (if exists)
|
|
||||||
if hasattr(settings, "REDIRECT_TABLE"):
|
|
||||||
if new_url[1] in settings.REDIRECT_TABLE:
|
|
||||||
new_url[1] = settings.REDIRECT_TABLE[new_url[1]]
|
|
||||||
if new_url != old_url:
|
|
||||||
# Force canonical hostname
|
|
||||||
if settings.FORCE_CANONICAL_HOSTNAME:
|
|
||||||
new_url[0] = settings.FORCE_CANONICAL_HOSTNAME
|
|
||||||
# Redirect
|
|
||||||
if new_url[0]:
|
|
||||||
newurl = "{}://{}{}".format(request.is_secure() and 'https' or 'http', new_url[0], new_url[1])
|
|
||||||
else:
|
|
||||||
newurl = new_url[1]
|
|
||||||
if request.GET:
|
|
||||||
newurl += '?' + request.GET.urlencode()
|
|
||||||
return http.HttpResponseRedirect(newurl)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def process_response(self, request, response):
|
|
||||||
# provide hints to squid
|
|
||||||
if request.method in ('GET', 'HEAD') and response.status_code == 200:
|
|
||||||
patch_response_headers(response)
|
|
||||||
return response
|
|
|
@ -105,11 +105,8 @@ def query(request):
|
||||||
|
|
||||||
def relative_redirect(request, path):
|
def relative_redirect(request, path):
|
||||||
from django import http
|
from django import http
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
host = http.get_host(request)
|
host = http.get_host(request)
|
||||||
if settings.FORCE_CANONICAL_HOSTNAME:
|
|
||||||
host = settings.FORCE_CANONICAL_HOSTNAME
|
|
||||||
|
|
||||||
url = "%s://%s%s" % (request.is_secure() and 'https' or 'http', host, path)
|
url = "%s://%s%s" % (request.is_secure() and 'https' or 'http', host, path)
|
||||||
return http.HttpResponseRedirect(url)
|
return http.HttpResponseRedirect(url)
|
||||||
|
|
|
@ -22,10 +22,6 @@ from pathlib import Path
|
||||||
SITE_ID = 2
|
SITE_ID = 2
|
||||||
ROOT_URLCONF = 'conservancy.urls'
|
ROOT_URLCONF = 'conservancy.urls'
|
||||||
|
|
||||||
REDIRECT_TABLE = {
|
|
||||||
'www.sf-conservancy.org': 'sfconservancy.org',
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
'version': 1,
|
'version': 1,
|
||||||
'disable_existing_loggers': False,
|
'disable_existing_loggers': False,
|
||||||
|
@ -136,7 +132,6 @@ MIDDLEWARE = [
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'conservancy.middleware.ForceCanonicalHostnameMiddleware',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
USETHESOURCE = {
|
USETHESOURCE = {
|
||||||
|
|
|
@ -3,8 +3,6 @@ from .base import *
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
FORCE_CANONICAL_HOSTNAME = False
|
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'NAME': 'conservancy-website.sqlite3',
|
'NAME': 'conservancy-website.sqlite3',
|
||||||
|
|
|
@ -7,8 +7,6 @@ from .base import *
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
ALLOWED_HOSTS = ['www.sfconservancy.org', 'sfconservancy.org']
|
ALLOWED_HOSTS = ['www.sfconservancy.org', 'sfconservancy.org']
|
||||||
|
|
||||||
FORCE_CANONICAL_HOSTNAME = 'sfconservancy.org'
|
|
||||||
|
|
||||||
ADMINS = [
|
ADMINS = [
|
||||||
('Bradley M. Kuhn', 'sysadmin@sfconservancy.org'),
|
('Bradley M. Kuhn', 'sysadmin@sfconservancy.org'),
|
||||||
('Ben Sturmfels', 'sysadmin+conservancy@sturm.com.au'),
|
('Ben Sturmfels', 'sysadmin+conservancy@sturm.com.au'),
|
||||||
|
|
Loading…
Reference in a new issue