Begin middleware revamp

This commit is contained in:
Adam Hopkins
2022-08-07 22:31:26 +03:00
parent 2f6f2bfa76
commit c72cbe4326
5 changed files with 208 additions and 98 deletions

View File

@@ -1,11 +1,17 @@
from collections import deque
from functools import partial
from operator import attrgetter
from typing import List
from sanic.base.meta import SanicMeta
from sanic.middleware import Middleware, MiddlewareLocation
from sanic.models.futures import FutureMiddleware
from sanic.router import Router
class MiddlewareMixin(metaclass=SanicMeta):
router: Router
def __init__(self, *args, **kwargs) -> None:
self._future_middleware: List[FutureMiddleware] = []
@@ -13,7 +19,12 @@ class MiddlewareMixin(metaclass=SanicMeta):
raise NotImplementedError # noqa
def middleware(
self, middleware_or_request, attach_to="request", apply=True
self,
middleware_or_request,
attach_to="request",
apply=True,
*,
priority=0
):
"""
Decorate and register middleware to be called before a request
@@ -30,6 +41,12 @@ class MiddlewareMixin(metaclass=SanicMeta):
def register_middleware(middleware, attach_to="request"):
nonlocal apply
location = (
MiddlewareLocation.REQUEST
if attach_to == "request"
else MiddlewareLocation.RESPONSE
)
middleware = Middleware(middleware, location, priority=priority)
future_middleware = FutureMiddleware(middleware, attach_to)
self._future_middleware.append(future_middleware)
if apply:
@@ -46,7 +63,7 @@ class MiddlewareMixin(metaclass=SanicMeta):
register_middleware, attach_to=middleware_or_request
)
def on_request(self, middleware=None):
def on_request(self, middleware=None, *, priority=0):
"""Register a middleware to be called before a request is handled.
This is the same as *@app.middleware('request')*.
@@ -54,11 +71,13 @@ class MiddlewareMixin(metaclass=SanicMeta):
:param: middleware: A callable that takes in request.
"""
if callable(middleware):
return self.middleware(middleware, "request")
return self.middleware(middleware, "request", priority=priority)
else:
return partial(self.middleware, attach_to="request")
return partial(
self.middleware, attach_to="request", priority=priority
)
def on_response(self, middleware=None):
def on_response(self, middleware=None, *, priority=0):
"""Register a middleware to be called after a response is created.
This is the same as *@app.middleware('response')*.
@@ -67,6 +86,31 @@ class MiddlewareMixin(metaclass=SanicMeta):
A callable that takes in a request and its response.
"""
if callable(middleware):
return self.middleware(middleware, "response")
return self.middleware(middleware, "response", priority=priority)
else:
return partial(self.middleware, attach_to="response")
return partial(
self.middleware, attach_to="response", priority=priority
)
def finalize_middleware(self):
for route in self.router.routes:
request_middleware = Middleware.convert(
self.request_middleware,
self.named_request_middleware.get(route.name, deque()),
location=MiddlewareLocation.REQUEST,
)
response_middleware = Middleware.convert(
self.response_middleware,
self.named_response_middleware.get(route.name, deque()),
location=MiddlewareLocation.RESPONSE,
)
route.extra.request_middleware = sorted(
request_middleware,
key=attrgetter("order"),
reverse=True,
)
route.extra.response_middleware = sorted(
response_middleware,
key=attrgetter("order"),
reverse=True,
)[::-1]