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: |  | ||||||
|     _HOST_URL_VAR = {'host_url': 'https://' + settings.FORCE_CANONICAL_HOSTNAME} |  | ||||||
|     def host_url(request): |  | ||||||
|         return _HOST_URL_VAR |  | ||||||
| else: |  | ||||||
| def host_url(request): | def host_url(request): | ||||||
|     return {'host_url': request.build_absolute_uri('/').rstrip('/')} |     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…
	
	Add table
		
		Reference in a new issue