Plain is headed towards 1.0! Subscribe for development updates →

 1from __future__ import annotations
 2
 3from collections.abc import Callable
 4from typing import TYPE_CHECKING
 5
 6from plain.http import ResponseRedirect
 7
 8if TYPE_CHECKING:
 9    from plain.http import Request, Response
10
11
12class RedirectionMiddleware:
13    def __init__(self, get_response: Callable[[Request], Response]) -> None:
14        self.get_response = get_response
15
16    def __call__(self, request: Request) -> Response:
17        response = self.get_response(request)
18
19        if response.status_code == 404:
20            from .models import NotFoundLog, Redirect, RedirectLog
21
22            redirects = Redirect.query.filter(enabled=True).only(
23                "id", "from_pattern", "to_pattern", "http_status", "is_regex"
24            )
25            for redirect in redirects:
26                if redirect.matches_request(request):
27                    # Log it
28                    redirect_log = RedirectLog.from_redirect(redirect, request)
29                    # Then redirect
30                    return ResponseRedirect(
31                        str(redirect_log.to_url), status_code=redirect.http_status
32                    )
33
34            # Nothing matched, just log the 404
35            NotFoundLog.from_request(request)
36
37        return response