WhisperMaPhone/whispermaphone/middleware.py

39 lines
1.8 KiB
Python

import re
from django import http
from django.conf import settings
from django.urls import is_valid_path
from django.core.exceptions import ImproperlyConfigured
from django.utils.deprecation import MiddlewareMixin
class RemoveSlashMiddleware(MiddlewareMixin):
def process_request(self, request):
if getattr(settings, "APPEND_SLASH") and getattr(settings, "REMOVE_SLASH"):
raise ImproperlyConfigured("APPEND_SLASH and REMOVE_SLASH may not both be True.")
old_url = request.path_info # path_info only includes path, query information
if getattr(settings, "REMOVE_SLASH", False) and old_url[-1] == "/":
urlconf = getattr(request, "urlconf", None)
new_url = old_url[:-1]
# If the url with a / would 404 and without a slash wouldn't
if (not is_valid_path(old_url, urlconf)) and is_valid_path(new_url, urlconf):
if settings.DEBUG and request.method == "POST":
if old_url.startswith("/api/"):
return api.error("You made a POST request to a URL ending with a slash. Please repeat your request without the slash.")
raise RuntimeError(""
"You called this URL via POST, but the URL ends in a "
"slash and you have REMOVE_SLASH set. Django can't "
"redirect to the non-slash URL while maintaining POST "
f"data. Change your form to point to {new_url} (without a "
"trailing slash), or set REMOVE_SLASH=False in your "
"Django settings.")
# The ? and everything after
query_data = re.match(r"^[^?]*(\?.*)?$", request.build_absolute_uri()).group(1) or ""
return http.HttpResponsePermanentRedirect(new_url + query_data)