2015-06-14 12 views
9

Когда я использую get_current_user () Мне нужно проверить несколько вещей в Redis (использование Торнадо-Redis) асинхронно.Получить текущего пользователя Async в Торнадо

Я делаю следующее:

def authenticated_async(method): 

    @gen.coroutine 
    def wrapper(self, *args, **kwargs): 
     self._auto_finish = False 
     self.current_user = yield gen.Task(self.get_current_user_async) 
     if not self.current_user: 
      self.redirect(self.reverse_url('login')) 
     else: 
      result = method(self, *args, **kwargs) # updates 
      if result is not None: 
       yield result 
    return wrapper 

class BaseClass(): 

    @gen.coroutine 
    def get_current_user_async(self,): 

     auth_cookie = self.get_secure_cookie('user') # cfae7a25-2b8b-46a6-b5c4-0083a114c40e 
     user_id = yield gen.Task(c.hget, 'auths', auth_cookie) # 16 
     print(123, user_id) 
     return auth_cookie if auth_cookie else None 

Например, я хочу использовать authenticated_async декоратора:

class IndexPageHandler(BaseClass, RequestHandler): 

    @authenticated_async 
    def get(self): 
     self.render("index.html") 

Но у меня в консоли только .

Что-то не так? Как это исправить?

Спасибо!

UPDATE

Я обновил код с yield result.

В auth_cookie У меня есть cfae7a25-2b8b-46a6-b5c4-0083a114c40e.

Тогда я иду к терминалу:

127.0.0.1:6379> hget auths cfae7a25-2b8b-46a6-b5c4-0083a114c40e 
"16" 

Так,

user_id = yield gen.Task(c.hget, 'auths', auth_cookie) 
print(123, user_id) 

Возвратить

123 16 

Но он возвращает один 123

UPDATE 1

С

class IndexPageHandler(BaseClass, RequestHandler): 
    @gen.coroutine 
    def get(self): 
     print('cookie', self.get_secure_cookie('user')) 
     user_async = yield self.get_current_user_async() 
     print('user_async', user_async) 
     print('current user', self.current_user) 
     self.render("index.html",) 

В консоли у меня есть:

cookie b'cfae7a25-2b8b-46a6-b5c4-0083a114c40e' 
123 
user_async b'cfae7a25-2b8b-46a6-b5c4-0083a114c40e' 
current user None 
+0

Если обернутый метод сам является сопрограммой coroutine, вы должны предоставить его при вызове из обертки authenticate_async ('result = method (* args, ** kwargs), если результат не равен None: result result') , Однако это не относится к этому «IndexPageHandler». Если вы добираетесь до утверждения print, похоже, что все асинхронные файлы работают, и вы просто получаете пустой результат из 'c.hget' (что бы это ни было). Если это не так, вы можете более четко узнать, что именно вы ожидаете и что видите вместо этого? –

+0

@BenDarnell Я обновил сообщение. – tim

+0

Работает ли он без декоратора? Что делать, если вы просто вызываете 'get_secure_cookie' и' c.hget' (или 'get_current_user_async') в' handler.get' напрямую? –

ответ

4

get_secure_cookie() возвращает байтовую строку; поскольку файл cookie распечатывается с префиксом b', вы должны быть на Python 3. На Python 3, tornado-redis, похоже, ожидает строки unicode вместо байтовых строк; любой ввод, который не является строкой в ​​юникоде, будет преобразован в один с функцией str().Это добавляет b' префикс видели выше, так что вы запрашиваете для b'cfae7a25-2b8b-46a6-b5c4-0083a114c40e', не cfae7a25-2b8b-46a6-b5c4-0083a114c40e

Решение состоит в том, чтобы преобразовать печенье в str перед его отправкой в ​​Redis: auth_cookie = tornado.escape.native_str(auth_cookie)

+0

большое спасибо! Оно работает! – tim

0

Взглянув на док строку gen.Task:

принимает функцию (и опциональный дополнительный аргументы) и запускает его с этими аргументами плюс аргумент ключевого слова callback.

Принимает ли c.hget аргумент обратного вызова? Если нет, обратный вызов вызовет исключение, в будущем не будет установлен результат, поэтому оператор печати не распечатает идентификатор пользователя.

+0

Я использую примеры здесь - https://github.com/leporo/tornado-redis#usage И выражения типа 'bar = yield tornado.gen.Task (c.get, 'bar') 'красиво работает – tim

0

Ответ обратно в обертку сопрограммы ,

 if result is not None: 
      yield result 

Вы не хотите давать результат, а «возвращать» его из сопрограммы. Однако, поскольку Python не позволяет использовать непустую отдачу от генератора, вам нужно поднять его как обернутое исключение того, что Торнадо может UnWrap, и передать результат вызывающих (get_current_user)

if result is not None: 
    raise gen.Return(result) 

Сделав это, вы должны найти его работу.

Смежные вопросы