aiohttp:装饰器序列链
aiohttp: chain of decorators sequence
考虑以下代码:
from aiohttp_mako import template
def authorize():
def wrapper(func):
@asyncio.coroutine
@functools.wraps(func)
def wrapped(*args):
allowed = # Some auth stuff
if not allowed:
return HTTPUnauthorized()
return func()
return wrapped
return wrapper
@authorize()
@template('admin.mak')
async def admin(request):
return dict(ok=True)
我希望 authorize()
' wrapper
得到 template
装饰器作为它的 func
所以我可以 return 它在我的 authorize
装饰器中生成的 Response
。但是 authorize()
' wrapper
将 admin()
协程作为 func
并以
结束
File "/Users/etemin/virtualenvs/onlinelux/lib/python3.5/site-packages/aiohttp/web.py", line 306, in _handle
resp = yield from handler(request)
File "/Users/etemin/virtualenvs/onlinelux/lib/python3.5/site-packages/aiohttp_session/__init__.py", line 134, in middleware
raise RuntimeError("Expect response, not {!r}", type(response))
RuntimeError: ('Expect response, not {!r}', <class 'generator'>)
因为它试图 return 协程。我应该如何到达 return template
装饰器?
你已经包装了一个协程,所以你需要等待那个协程(从中产生):
def authorize():
def wrapper(func):
@asyncio.coroutine
@functools.wraps(func)
def wrapped(*args):
allowed = # Some auth stuff
if not allowed:
return HTTPUnauthorized()
return yield from func()
return wrapped
return wrapper
因为你已经在使用 async
/await
语法,我也只是在这里使用它而不是使用 @asyncio.coroutine
:
def authorize():
async def wrapper(func):
@functools.wraps(func)
async def wrapped(*args):
allowed = # Some auth stuff
if not allowed:
return HTTPUnauthorized()
return await func()
return wrapped
return wrapper
请注意,我在 func()
那里等待,并返回了结果。
这对我有用。
灵感来自 @aiohttp_csrf.csrf_protect.
from functools import wraps
from aiohttp import web
def is_authorized(request):
# Write logic to validate request
return True
def authorize(handler=None): # When python module having view was imported, it expected to have this.
def wrapper(handler):
@wraps(handler)
async def wrapped(*args, **kwargs):
request = args[-1]
if isinstance(request, web.View):
# Should also work for Class-Based Views
request = request.request
try:
is_authorized(request)
except Exception as ex:
# request not authorized. Write logic to handle it accordingly
print('Request not authorized: ', repr(ex))
raise ex
response = await handler(*args, **kwargs)
return response
return wrapped
if handler is None:
return wrapper
return wrapper(handler)
在您看来的某处:
@authorize()
@template('admin.mak')
async def admin(request):
return dict(ok=True)
考虑以下代码:
from aiohttp_mako import template
def authorize():
def wrapper(func):
@asyncio.coroutine
@functools.wraps(func)
def wrapped(*args):
allowed = # Some auth stuff
if not allowed:
return HTTPUnauthorized()
return func()
return wrapped
return wrapper
@authorize()
@template('admin.mak')
async def admin(request):
return dict(ok=True)
我希望 authorize()
' wrapper
得到 template
装饰器作为它的 func
所以我可以 return 它在我的 authorize
装饰器中生成的 Response
。但是 authorize()
' wrapper
将 admin()
协程作为 func
并以
File "/Users/etemin/virtualenvs/onlinelux/lib/python3.5/site-packages/aiohttp/web.py", line 306, in _handle
resp = yield from handler(request)
File "/Users/etemin/virtualenvs/onlinelux/lib/python3.5/site-packages/aiohttp_session/__init__.py", line 134, in middleware
raise RuntimeError("Expect response, not {!r}", type(response))
RuntimeError: ('Expect response, not {!r}', <class 'generator'>)
因为它试图 return 协程。我应该如何到达 return template
装饰器?
你已经包装了一个协程,所以你需要等待那个协程(从中产生):
def authorize():
def wrapper(func):
@asyncio.coroutine
@functools.wraps(func)
def wrapped(*args):
allowed = # Some auth stuff
if not allowed:
return HTTPUnauthorized()
return yield from func()
return wrapped
return wrapper
因为你已经在使用 async
/await
语法,我也只是在这里使用它而不是使用 @asyncio.coroutine
:
def authorize():
async def wrapper(func):
@functools.wraps(func)
async def wrapped(*args):
allowed = # Some auth stuff
if not allowed:
return HTTPUnauthorized()
return await func()
return wrapped
return wrapper
请注意,我在 func()
那里等待,并返回了结果。
这对我有用。
灵感来自 @aiohttp_csrf.csrf_protect.
from functools import wraps
from aiohttp import web
def is_authorized(request):
# Write logic to validate request
return True
def authorize(handler=None): # When python module having view was imported, it expected to have this.
def wrapper(handler):
@wraps(handler)
async def wrapped(*args, **kwargs):
request = args[-1]
if isinstance(request, web.View):
# Should also work for Class-Based Views
request = request.request
try:
is_authorized(request)
except Exception as ex:
# request not authorized. Write logic to handle it accordingly
print('Request not authorized: ', repr(ex))
raise ex
response = await handler(*args, **kwargs)
return response
return wrapped
if handler is None:
return wrapper
return wrapper(handler)
在您看来的某处:
@authorize()
@template('admin.mak')
async def admin(request):
return dict(ok=True)