0

トルネードについて頭を悩ませようとしています。私はmongodbに裏打ちされたチャットアプリケーションを作成しており、motorそれへの非ブロックアクセスに使用しています。

私が達成しようとしているのは次のとおりです。

  1. motormongo からユーザーのレコードを非同期にプルするために使用するデコレーターを作成します。
  2. 資格情報を検証する (ユーザー名とトークン)
  3. 上記1.で取得したuser_idがチャットルームへのアクセスを許可されていることを確認する別のデコレーターを作成します。motorこれには、「ChatRoom」レコードを取得するために、mongo への別の非同期呼び出しが必要です。
  4. 問題がなければチャットルームに登録する

デコレータ 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

問題は、2 番目のデコレータの場合、 にアクセスする必要があることですself.current_user。これは非同期コールバックで設定されるため、デコレーターに入ったときには使用できませんvalidation(つまり、認証デコレーターが完了する前に検証デコレーターが呼び出されます)。

非同期関数でこのようにデコレータを使用することはできませんか? True であることを確認した後、上記のメソッド内で検証メソッドを呼び出すだけでよいself.current_userので、コールバックのようになりますか?

Handler のメソッドをこれらのデコレータの両方でラップして、別の場所で再利用できるようにしたいのが理想です。

class ChatSocketHandler(tornado.websocket.WebSocketHandler):
    @gen.coroutine
    @validate_invitation_access_async
    @authenticated_async
    def open(self, invitation_id):
        # do stuff here...

更新 実際、依存関係はありません。user_id はパラメーターとして提供され、両方のデコレーターを並行して実行するために使用できます。1 つは認証を確認するため、もう 1 つはその ID を持つユーザーがルームへのアクセスを許可されているかどうかを確認するためです。open()メソッドは、の場合にのみ続行されますself.auth_check == True and self.room_check == True

open()ただし、非同期デコレータが完了する前に呼び出されることはありますか?

4

1 に答える 1

0

validate_invitation_access_asyncラッパーが current_user にアクセスできるように、デコレーターの順序を切り替える必要があります。

@authenticated_async
@validate_invitation_access_async
def open(self, invitation_id):
        # do stuff here...

次に、内部のラッパーvalidate_invitation_access_asyncは "f" inauthenticated_asyncです: self.current_user が設定された後に呼び出されます。追加のデコレーターは必要ないことに注意してくださいgen.engine。すべてのラッパーは既にエンジンになっています。ラッパーは次のようになります。

def validate_invitation_access_async(f):
    @gen.engine
    def wrapper(self, *args, **kwargs):
        # ... use Motor to see if user is authorized ...
        # if not, log and redirect. otherwise:
        f(self, *args, **kwargs)

また、gen.engine の代わりに Tornado 3 の gen.coroutine を使用するようにコードを更新する必要があります。これははるかにクリーンです。しかし、私はそれを演習として残します。

于 2014-03-10T16:00:33.417 に答える