Search code examples
pythonpython-3.xtornadocoroutinepython-asyncio

User authentication: prepare vs get_current_user in tornado


I need to authenticate a user from a cookie in an application running on Tornado. I need to parse the cookie and load the user from the DB using the cookie content. On checking out the Tornado RequestHandler documentation, there are 2 ways of doing it:

  • by overriding prepare() method of RequestHandler class.
  • by overriding get_current_user() method of RequestHandler class.

I'm confused with the following statement:

Note that prepare() may be a coroutine while get_current_user() may not, so the latter form is necessary if loading the user requires asynchronous operations.

I don't understand 2 things in it:

  1. What does the doc mean by saying that get_current_user() may not be a coroutine? What does may not mean here? Either it can be a coroutine, or it can't.

  2. Why is the latter form, i.e. get_current_user(), required if async operation is required? If prepare() can be a coroutine and get_current_user() may not, then shouldn't prepare() be used for async operations?

I would really appreciate any help with this.


Solution

    1. Here, "may not be a coroutine" means "is not allowed to be a coroutine" or "must not be a coroutine". The language used is confusing and it should probably be changed to say "must not".

    2. Again, the docs are confusing: in this sentence prepare() is mentioned first, but before this sentence are two examples and get_current_user is first. "Latter" refers to the second example which uses prepare().

    So in summary, it always works to override prepare() and set self.current_user, whether you need a coroutine or not. If you don't need a coroutine to get the current user, you can override get_current_user() instead and it will be called automatically the first time self.current_user is accessed. It doesn't really matter which one you choose; you can use whichever feels more natural to you. (The reason we have two different methods is that get_current_user() is older but we had to use a different method for coroutines)