spiderweb/spiderweb/middleware/__init__.py
2024-09-01 21:05:43 -04:00

65 lines
2.3 KiB
Python

from typing import Callable, ClassVar
import sys
from .base import SpiderwebMiddleware as SpiderwebMiddleware
from .cors import CorsMiddleware as CorsMiddleware
from .csrf import CSRFMiddleware as CSRFMiddleware
from .sessions import SessionMiddleware as SessionMiddleware
from ..exceptions import ConfigError, UnusedMiddleware, StartupErrors
from ..request import Request
from ..response import HttpResponse
from ..utils import import_by_string
class MiddlewareMixin:
"""Cannot be called on its own. Requires context of SpiderwebRouter."""
_middleware: list[str]
middleware: list[ClassVar]
fire_response: Callable
def init_middleware(self):
if self._middleware:
middleware_by_reference = []
for m in self._middleware:
try:
middleware_by_reference.append(import_by_string(m)(server=self))
except ImportError:
raise ConfigError(f"Middleware '{m}' not found.")
self.middleware = middleware_by_reference
def run_middleware_checks(self):
errors = []
for middleware in self.middleware:
if hasattr(middleware, "checks"):
for check in middleware.checks:
if issue := check(server=self).check():
errors.append(issue)
if errors:
# just show the messages
sys.tracebacklimit = 0
raise StartupErrors(
"Problems were identified during startup — cannot continue.", errors
)
def process_request_middleware(self, request: Request) -> None | bool:
for middleware in self.middleware:
try:
resp = middleware.process_request(request)
except UnusedMiddleware:
self.middleware.remove(middleware)
continue
if resp:
self.process_response_middleware(request, resp)
return resp # abort further processing
def process_response_middleware(
self, request: Request, response: HttpResponse
) -> None:
for middleware in reversed(self.middleware):
try:
middleware.process_response(request, response)
except UnusedMiddleware:
self.middleware.remove(middleware)
continue