GIT-37: fix blueprint middleware application (#1690)
* GIT-37: fix blueprint middleware application 1. If you register a middleware via `@blueprint.middleware` then it will apply only to the routes defined by the blueprint. 2. If you register a middleware via `@blueprint_group.middleware` then it will apply to all blueprint based routes that are part of the group. 3. If you define a middleware via `@app.middleware` then it will be applied on all available routes Fixes #37 Signed-off-by: Harsha Narayana <harsha2k4@gmail.com> * GIT-37: add changelog Signed-off-by: Harsha Narayana <harsha2k4@gmail.com>
This commit is contained in:
committed by
Stephen Sadowski
parent
179a07942e
commit
a6077a1790
67
sanic/app.py
67
sanic/app.py
@@ -85,7 +85,8 @@ class Sanic:
|
||||
self.is_request_stream = False
|
||||
self.websocket_enabled = False
|
||||
self.websocket_tasks = set()
|
||||
|
||||
self.named_request_middleware = {}
|
||||
self.named_response_middleware = {}
|
||||
# Register alternative method names
|
||||
self.go_fast = self.run
|
||||
|
||||
@@ -178,7 +179,7 @@ class Sanic:
|
||||
:param stream:
|
||||
:param version:
|
||||
:param name: user defined route name for url_for
|
||||
:return: decorated function
|
||||
:return: tuple of routes, decorated function
|
||||
"""
|
||||
|
||||
# Fix case where the user did not prefix the URL with a /
|
||||
@@ -204,7 +205,7 @@ class Sanic:
|
||||
if stream:
|
||||
handler.is_stream = stream
|
||||
|
||||
self.router.add(
|
||||
routes = self.router.add(
|
||||
uri=uri,
|
||||
methods=methods,
|
||||
handler=handler,
|
||||
@@ -213,7 +214,7 @@ class Sanic:
|
||||
version=version,
|
||||
name=name,
|
||||
)
|
||||
return handler
|
||||
return routes, handler
|
||||
|
||||
return response
|
||||
|
||||
@@ -462,7 +463,7 @@ class Sanic:
|
||||
:param subprotocols: optional list of str with supported subprotocols
|
||||
:param name: A unique name assigned to the URL so that it can
|
||||
be used with :func:`url_for`
|
||||
:return: decorated function
|
||||
:return: tuple of routes, decorated function
|
||||
"""
|
||||
self.enable_websocket()
|
||||
|
||||
@@ -515,7 +516,7 @@ class Sanic:
|
||||
self.websocket_tasks.remove(fut)
|
||||
await ws.close()
|
||||
|
||||
self.router.add(
|
||||
routes = self.router.add(
|
||||
uri=uri,
|
||||
handler=websocket_handler,
|
||||
methods=frozenset({"GET"}),
|
||||
@@ -523,7 +524,7 @@ class Sanic:
|
||||
strict_slashes=strict_slashes,
|
||||
name=name,
|
||||
)
|
||||
return handler
|
||||
return routes, handler
|
||||
|
||||
return response
|
||||
|
||||
@@ -544,6 +545,7 @@ class Sanic:
|
||||
:param host: Host IP or FQDN details
|
||||
:param uri: URL path that will be mapped to the websocket
|
||||
handler
|
||||
handler
|
||||
:param strict_slashes: If the API endpoint needs to terminate
|
||||
with a "/" or not
|
||||
:param subprotocols: Subprotocols to be used with websocket
|
||||
@@ -645,6 +647,22 @@ class Sanic:
|
||||
self.response_middleware.appendleft(middleware)
|
||||
return middleware
|
||||
|
||||
def register_named_middleware(
|
||||
self, middleware, route_names, attach_to="request"
|
||||
):
|
||||
if attach_to == "request":
|
||||
for _rn in route_names:
|
||||
if _rn not in self.named_request_middleware:
|
||||
self.named_request_middleware[_rn] = deque()
|
||||
if middleware not in self.named_request_middleware[_rn]:
|
||||
self.named_request_middleware[_rn].append(middleware)
|
||||
if attach_to == "response":
|
||||
for _rn in route_names:
|
||||
if _rn not in self.named_response_middleware:
|
||||
self.named_response_middleware[_rn] = deque()
|
||||
if middleware not in self.named_response_middleware[_rn]:
|
||||
self.named_response_middleware[_rn].append(middleware)
|
||||
|
||||
# Decorator
|
||||
def middleware(self, middleware_or_request):
|
||||
"""
|
||||
@@ -916,20 +934,23 @@ class Sanic:
|
||||
# allocation before assignment below.
|
||||
response = None
|
||||
cancelled = False
|
||||
name = None
|
||||
try:
|
||||
# Fetch handler from router
|
||||
handler, args, kwargs, uri, name = self.router.get(request)
|
||||
|
||||
# -------------------------------------------- #
|
||||
# Request Middleware
|
||||
# -------------------------------------------- #
|
||||
response = await self._run_request_middleware(request)
|
||||
response = await self._run_request_middleware(
|
||||
request, request_name=name
|
||||
)
|
||||
# No middleware results
|
||||
if not response:
|
||||
# -------------------------------------------- #
|
||||
# Execute Handler
|
||||
# -------------------------------------------- #
|
||||
|
||||
# Fetch handler from router
|
||||
handler, args, kwargs, uri = self.router.get(request)
|
||||
|
||||
request.uri_template = uri
|
||||
if handler is None:
|
||||
raise ServerError(
|
||||
@@ -993,7 +1014,7 @@ class Sanic:
|
||||
if response is not None:
|
||||
try:
|
||||
response = await self._run_response_middleware(
|
||||
request, response
|
||||
request, response, request_name=name
|
||||
)
|
||||
except CancelledError:
|
||||
# Response middleware can timeout too, as above.
|
||||
@@ -1265,10 +1286,14 @@ class Sanic:
|
||||
if isawaitable(result):
|
||||
await result
|
||||
|
||||
async def _run_request_middleware(self, request):
|
||||
async def _run_request_middleware(self, request, request_name=None):
|
||||
# The if improves speed. I don't know why
|
||||
if self.request_middleware:
|
||||
for middleware in self.request_middleware:
|
||||
named_middleware = self.named_request_middleware.get(
|
||||
request_name, deque()
|
||||
)
|
||||
applicable_middleware = self.request_middleware + named_middleware
|
||||
if applicable_middleware:
|
||||
for middleware in applicable_middleware:
|
||||
response = middleware(request)
|
||||
if isawaitable(response):
|
||||
response = await response
|
||||
@@ -1276,9 +1301,15 @@ class Sanic:
|
||||
return response
|
||||
return None
|
||||
|
||||
async def _run_response_middleware(self, request, response):
|
||||
if self.response_middleware:
|
||||
for middleware in self.response_middleware:
|
||||
async def _run_response_middleware(
|
||||
self, request, response, request_name=None
|
||||
):
|
||||
named_middleware = self.named_response_middleware.get(
|
||||
request_name, deque()
|
||||
)
|
||||
applicable_middleware = self.response_middleware + named_middleware
|
||||
if applicable_middleware:
|
||||
for middleware in applicable_middleware:
|
||||
_response = middleware(request, response)
|
||||
if isawaitable(_response):
|
||||
_response = await _response
|
||||
|
||||
Reference in New Issue
Block a user