1

I have written a simple Tornado app. It has a homepage, if the user is logged in, it says user is logged or else it has a link to login. Here is the full script and I have set up website url as localhost:8000 in my FB app settings :

#!/usr/bin/env python

import os.path
import os

import tornado.auth
import tornado.escape
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options

from settings import *

define("port", default=8000, help="run on the given port", type=int)

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
             (r'/', MainHandler),
             (r'/auth/login', LoginHandler),
             (r'/auth/logout',  LogoutHandler)
        ]
        settings = application_handler_setttings
        tornado.web.Application.__init__(self, handlers, **settings)

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        userID = self.get_secure_cookie('user_id')
        if userID:
            self.render("index.html")
        else:
            self.render("login.html")

class LoginHandler(tornado.web.RequestHandler, tornado.auth.FacebookGraphMixin):
    @tornado.web.asynchronous
    def get(self):
        userID = self.get_secure_cookie('user_id')

        if self.get_argument('code', None):
            self.get_authenticated_user(
                redirect_uri='http://localhost:8000/auth/login',
                client_id=self.settings['facebook_api_key'],
                client_secret=self.settings['facebook_secret'],
                code=self.get_argument('code'),
                callback=self.async_callback(self._on_facebook_login))
            return
        elif self.get_secure_cookie('access_token'):
            self.redirect('/')

        self.authorize_redirect(
            redirect_uri='http://localhost:8000/auth/login ',
            client_id=self.settings['facebook_api_key'],
            extra_params={'scope': 'user_photos, publish_stream'}
        )

    def _on_facebook_login(self, user):
        if not user:
            self.clear_all_cookies()
            raise tornado.web.HTTPError(500, 'Facebook authentication failed')

        self.set_secure_cookie('user_id', str(user['id']))
        self.set_secure_cookie('user_name', str(user['name']))
        self.set_secure_cookie('access_token', str(user['access_token']))
        self.redirect('/')

class LogoutHandler(tornado.web.RequestHandler):
    def get(self):
        self.clear_all_cookies()
        self.render('logout.html')

def main():
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()


if __name__ == "__main__":
    main()

my settings.py file:

import os
application_handler_setttings = dict(
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            facebook_api_key= '1...3',
            facebook_secret= '7...d',
            cookie_secret= 'N...g',
            debug=True,
            )

Here is the issue. When I authenticate my app and when it redirects back, the url in browser changes and some strange string is present, it is http://localhost:8000/#_=_. I am not able to understand, why such string is being appended.

enter image description here

Secondly, if I enter any url starting with #, it is not throwing 404 error, because I have not defined any handler. Why is that? For example, even if I enter http://localhost:8000/#fghdgdh it shows the index page. Well, I find that strange.

Lastly, is it possible to keep all my handler class definitions in in separate files? And also the list of tuple of url and handler functions, is it possible to keep this also in some separate file other than these class definitions and the in the main script?

avi
  • 9,292
  • 11
  • 47
  • 84

1 Answers1

0

The first part is a duplicate question as you can see in the comments.

Second part: things followed by # in an url is called Fragment Identifier. It points to some resource inside the primary resource(in your case, the HTML file).

In URIs for MIME text/html pages such as http://www.example.org/foo.html#bar the fragment refers to the element with id="bar".

404 is returned if the HTML document is not found, not for fragments.

Last part: Yes you can. Just move them to some other file, say handler.py and import them where you need, like

from handlers import LoginHandler

And it should work.

Bibhas Debnath
  • 14,559
  • 17
  • 68
  • 96