Open minrk opened 6 years ago
@minrk , maybe you can set current_user asynchronously in prepare,prepare is called just before the real request handler and it's can be asynchronous!
Yeah, a standardized async implementation of authenticated
/get_current_user
is a good idea (although a prepare()
-based solution is a decent workaround for now). The biggest stumbling block is the old current_user
property - we can't make get_current_user
lazy any more (that laziness is also imperfect and broken by the use of tornado.template
: #820).
I think it would be possible to extend the current implementation in a mostly backwards-compatible way (e.g. "if get_current_user_async is defined, @authenticated
will call it and store its result in handler.current_user
. current_user
may only be used from handlers with @authenticated
(and maybe a new optional-authenticated decorator), instead of being usable from any handler as it is now). However, it might be cleaner to redesign the whole setup.
Other issues with the current system:
await self.check_authentication()
at the start of the method, and the latter is easier to both understand and customize. (or going to the other extreme, some sort of wrapper in the routing table would be a better way to do this magically)So as a strawman, what about something like this?
class RequestHandler:
...
async def get_current_user_async(self):
"""Override instead of get_current_user to use a coroutine."""
raise NotImplementedError()
async def check_authentication(self, optional=False):
if not hasattr(self, '_current_user'):
try:
self._current_user = await self.get_current_user_async()
except NotImplementedError:
self._current_user = self.get_current_user()
if self._current_user is None and not optional:
if login_url_is_configured():
redirect_to_login()
else:
raise HTTPError(403)
Is it in-scope for
@web.authenticated
to support an async.get_current_user()
? Or does this belong more appropriately in custom auth decorators in applications? It seems generic enough to me to warrant a default implementation, but making surehandler.current_user
access works in a backward-compatible way seems tricky.