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