add a new feature which supports adding middlewares to specific handlers
This commit is contained in:
parent
ef465fb5fe
commit
3060dd2237
66
sanic/app.py
66
sanic/app.py
|
@ -3,7 +3,7 @@ import logging.config
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
from asyncio import get_event_loop, ensure_future, CancelledError
|
from asyncio import get_event_loop, ensure_future, CancelledError
|
||||||
from collections import deque, defaultdict
|
from collections import deque, defaultdict, Iterable
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from inspect import isawaitable, stack, getmodulename
|
from inspect import isawaitable, stack, getmodulename
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
|
@ -12,7 +12,7 @@ from ssl import create_default_context, Purpose
|
||||||
|
|
||||||
from sanic.config import Config, LOGGING
|
from sanic.config import Config, LOGGING
|
||||||
from sanic.constants import HTTP_METHODS
|
from sanic.constants import HTTP_METHODS
|
||||||
from sanic.exceptions import ServerError, URLBuildError, SanicException
|
from sanic.exceptions import ServerError, URLBuildError, SanicException, MiddlewareTypeError
|
||||||
from sanic.handlers import ErrorHandler
|
from sanic.handlers import ErrorHandler
|
||||||
from sanic.log import log
|
from sanic.log import log
|
||||||
from sanic.response import HTTPResponse, StreamingHTTPResponse
|
from sanic.response import HTTPResponse, StreamingHTTPResponse
|
||||||
|
@ -110,7 +110,7 @@ class Sanic:
|
||||||
|
|
||||||
# Decorator
|
# Decorator
|
||||||
def route(self, uri, methods=frozenset({'GET'}), host=None,
|
def route(self, uri, methods=frozenset({'GET'}), host=None,
|
||||||
strict_slashes=False):
|
strict_slashes=False, middleware=None):
|
||||||
"""Decorate a function to be registered as a route
|
"""Decorate a function to be registered as a route
|
||||||
|
|
||||||
:param uri: path of the URL
|
:param uri: path of the URL
|
||||||
|
@ -125,6 +125,21 @@ class Sanic:
|
||||||
uri = '/' + uri
|
uri = '/' + uri
|
||||||
|
|
||||||
def response(handler):
|
def response(handler):
|
||||||
|
# attach middleware to specific handler
|
||||||
|
if middleware:
|
||||||
|
for r in ('request', 'response'):
|
||||||
|
mid = middleware[r]
|
||||||
|
if mid:
|
||||||
|
if callable(mid):
|
||||||
|
vars(handler)["_"+r+"_middleware"] = mid,
|
||||||
|
elif isinstance(mid, Iterable):
|
||||||
|
vars(handler)['_'+r+'_middleware'] = tuple(mid)
|
||||||
|
else:
|
||||||
|
raise MiddlewareTypeError(
|
||||||
|
"Middleware mounted on a handler should "
|
||||||
|
"be a function or a sequence of functions"
|
||||||
|
)
|
||||||
|
|
||||||
self.router.add(uri=uri, methods=methods, handler=handler,
|
self.router.add(uri=uri, methods=methods, handler=handler,
|
||||||
host=host, strict_slashes=strict_slashes)
|
host=host, strict_slashes=strict_slashes)
|
||||||
return handler
|
return handler
|
||||||
|
@ -451,12 +466,9 @@ class Sanic:
|
||||||
|
|
||||||
request.app = self
|
request.app = self
|
||||||
response = await self._run_request_middleware(request)
|
response = await self._run_request_middleware(request)
|
||||||
|
|
||||||
# No middleware results
|
# No middleware results
|
||||||
if not response:
|
if not response:
|
||||||
# -------------------------------------------- #
|
|
||||||
# Execute Handler
|
|
||||||
# -------------------------------------------- #
|
|
||||||
|
|
||||||
# Fetch handler from router
|
# Fetch handler from router
|
||||||
handler, args, kwargs, uri = self.router.get(request)
|
handler, args, kwargs, uri = self.router.get(request)
|
||||||
request.uri_template = uri
|
request.uri_template = uri
|
||||||
|
@ -465,10 +477,30 @@ class Sanic:
|
||||||
("'None' was returned while requesting a "
|
("'None' was returned while requesting a "
|
||||||
"handler from the router"))
|
"handler from the router"))
|
||||||
|
|
||||||
|
# request middleware mounted on handler
|
||||||
|
mounted_request_middleware = handler._request_middleware
|
||||||
|
if mounted_request_middleware:
|
||||||
|
response = await self._handle_mounted_request_middleware(
|
||||||
|
mounted_request_middleware, request, *args, **kwargs
|
||||||
|
)
|
||||||
|
# No mounted request middleware result
|
||||||
|
if not response:
|
||||||
|
# -------------------------------------------- #
|
||||||
|
# Execute Handler
|
||||||
|
# -------------------------------------------- #
|
||||||
# Run response handler
|
# Run response handler
|
||||||
response = handler(request, *args, **kwargs)
|
response = handler(request, *args, **kwargs)
|
||||||
if isawaitable(response):
|
if isawaitable(response):
|
||||||
response = await response
|
response = await response
|
||||||
|
|
||||||
|
# response middleware mounted on handler
|
||||||
|
mounted_response_middleware = handler._response_middleware
|
||||||
|
if mounted_response_middleware:
|
||||||
|
response = await self._handle_mounted_response_middleware(
|
||||||
|
mounted_response_middleware, request, response, *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
# Response Generation Failed
|
# Response Generation Failed
|
||||||
|
@ -624,6 +656,26 @@ class Sanic:
|
||||||
break
|
break
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
async def _handle_mounted_request_middleware(self, middleware, request, *args, **kwargs):
|
||||||
|
for mid in middleware:
|
||||||
|
response = mid(request, *args, **kwargs)
|
||||||
|
if isawaitable(response):
|
||||||
|
response = await response
|
||||||
|
if response:
|
||||||
|
break
|
||||||
|
return response
|
||||||
|
|
||||||
|
async def _handle_mounted_response_middleware(self, middleware, request, response, *args, **kwargs):
|
||||||
|
for mid in middleware:
|
||||||
|
_response = mid(request, response, *args, **kwargs)
|
||||||
|
if isawaitable(_response):
|
||||||
|
_response = await _response
|
||||||
|
if _response:
|
||||||
|
response = _response
|
||||||
|
break
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
def _helper(self, host="127.0.0.1", port=8000, debug=False,
|
def _helper(self, host="127.0.0.1", port=8000, debug=False,
|
||||||
ssl=None, sock=None, workers=1, loop=None,
|
ssl=None, sock=None, workers=1, loop=None,
|
||||||
protocol=HttpProtocol, backlog=100, stop_event=None,
|
protocol=HttpProtocol, backlog=100, stop_event=None,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user