【发布时间】:2014-03-10 15:27:53
【问题描述】:
我正试图绕过 Tornado。我正在编写一个由 mongodb 支持的聊天应用程序,我正在使用 motor 对其进行非阻塞访问。
我想要实现的是:
- 创建一个使用
motor从mongo异步拉取用户记录的装饰器 - 验证他们的凭据(用户名和令牌)
- 创建另一个装饰器,检查上面 1. 中检索到的 user_id 是否被允许访问聊天室。这需要使用
motor再次异步调用 mongo 以检索“ChatRoom”记录。 - 如果一切正常,请订阅聊天室
我有装饰器 1. 工作(基本上取自 http://tornadogists.org/5251927/):
def authenticated_async(f):
@functools.wraps(f)
@gen.engine
def wrapper(self, *args, **kwargs):
self.current_user = yield gen.Task(self.get_current_user_async)
if self.current_user:
logging.info("User '%s' (%s) successfully authenticated" %
(self.current_user['username'],
self.current_user['_id']))
f(self, *args, **kwargs)
else:
raise tornado.web.HTTPError(401, "User not authenticated, "
"aborting")
return wrapper
麻烦的是,对于第二个装饰器,我需要访问self.current_user。因为这是在异步回调中设置的,所以当我进入我的 validation 装饰器时它不可用(即在 auth 装饰器完成之前调用验证装饰器)。
我不可能以这种方式将装饰器与异步函数一起使用吗?在确保self.current_user为True之后,我是否只需要在上述方法中调用验证方法,这样它更像是一个回调?
理想情况下,我希望我的处理程序中的方法与这两个装饰器一起包装,以便我可以在其他地方重用它们,即:
class ChatSocketHandler(tornado.websocket.WebSocketHandler):
@gen.coroutine
@validate_invitation_access_async
@authenticated_async
def open(self, invitation_id):
# do stuff here...
更新
事实上,没有依赖关系。 user_id 作为参数提供,可用于并行运行两个装饰器 - 一个用于确认身份验证,另一个用于查看是否允许具有该 ID 的用户访问房间。 open() 方法只有在 self.auth_check == True and self.room_check == True 时才会继续。
可以在异步装饰器完成之前调用open() 吗?
【问题讨论】:
标签: asynchronous tornado tornado-motor