selecta-highscore/highscore/app/middleware.py

30 lines
1.3 KiB
Python

from collections.abc import Callable
from django.http import HttpRequest, HttpResponse
class ScriptPrefixPathMiddleware:
"""Re-add the ``FORCE_SCRIPT_NAME`` prefix to ``request.path`` under ASGI.
Django's ASGI handler sets ``request.path = scope["path"]`` verbatim (see
``django/core/handlers/asgi.py``). When the reverse proxy strips the
script-name prefix (e.g. ``/scores``) before forwarding, ``request.path`` —
and therefore ``get_full_path()`` — loses the prefix, even though
``reverse()`` still prepends it via the script prefix. The result is the
admin login form posting to ``/admin/login/?next=/admin/`` instead of
``/scores/admin/login/?next=/scores/admin/``.
URL resolution is unaffected (it uses ``path_info``), so we only need to
realign the path-based URLs with the reverse()-based ones. The check is
idempotent: if the proxy already forwards the prefix, this is a no-op.
"""
def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]) -> None:
self.get_response = get_response
def __call__(self, request: HttpRequest) -> HttpResponse:
script_name = request.META.get("SCRIPT_NAME", "").rstrip("/")
if script_name and not request.path.startswith(f"{script_name}/"):
request.path = f"{script_name}{request.path}"
return self.get_response(request)