L
L
Leo2015-06-15 19:58:07
Python
Leo, 2015-06-15 19:58:07

How do get_current_user() execute asynchronously in Tornado?

What is the problem.
During the call to get_current_user() in Tornado, some asynchronous requests need to be made.
Attempts to make get_current_user() asynchronous failed, so the decision was made to write our own bike.

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)
            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')
        user_id = yield gen.Task(c.hget, 'auths', auth_cookie)
        print(123, user_id)
        return auth_cookie if auth_cookie else None

The example uses Redis , from which we take the value from hash .
The problem is that when I use the @authenticated_async decorator , the console output should be something other than the lone 123. Example:
class IndexPageHandler(BaseClass, RequestHandler):

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

What is the problem, why user_id is empty and how to fix it?
Maybe someone has already made the get_current_user() method asynchronous, share the implementation.
Thank you!

Answer the question

In order to leave comments, you need to log in

2 answer(s)
L
Leo, 2015-06-18
@STLEON

The code is correct, except
Since it's using Python 3, tornado-redis expects unicode strings, not bytes.
So it will handle non unicode string str() .
Therefore, you need to use:

auth_cookie = tornado.escape.native_str(self.get_secure_cookie('user'))

M
mooody, 2017-07-14
@mooody

class BaseHandler(RequestHandler):
    async def get_current_user_async(self):
        session_hash = self.get_secure_cookie("session_hash")
        return session_hash

def authenticated_async(method):
    @functools.wraps(method)
    async def wrapper(self, *args, **kwargs):
        if not await self.get_current_user_async():
            if self.request.method in ("GET", "HEAD"):
                url = self.get_login_url()
                if "?" not in url:
                    if urlparse.urlsplit(url).scheme:
                        # if login url is absolute, make next absolute too
                        next_url = self.request.full_url()
                    else:
                        next_url = self.request.uri
                    url += "?" + urlencode(dict(expired=next_url))
                self.redirect(url)
                return
            raise HTTPError(403)
        return await method(self, *args, **kwargs)
    return wrapper

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question