import logging import os import redis import tornado import tornado.ioloop import tornado.options from .handler import IndexHandler, RedirectHandler, ExpandHandler, ShortHandler # Define command line parameters. tornado.options.define('port', type=int, default=int(os.environ.get('PORT', 8888)), help='Listen on this port') tornado.options.define('domain', type=str, default=str(os.environ.get('DOMAIN', 'localhost:8888')), help='The default domain for shortening URLs') tornado.options.define('localhostonly', type=bool, default=bool(os.environ.get('LOCALHOSTONLY', False)), help='Listen on localhost only') tornado.options.define('salt', type=str, default=str(os.environ.get('SALT', '')), help='A string influencing the generated hashes') tornado.options.define('redis_host', type=str, default=str(os.environ.get('REDIS_HOST', 'localhost')), help='The redis host') tornado.options.define('redis_port', type=int, default=int(os.environ.get('REDIS_PORT', 6379)), help='The redis port') tornado.options.define('redis_db', type=int, default=int(os.environ.get('REDIS_DB', 0)), help='The redis db') tornado.options.define('redis_namespace', type=str, default=str(os.environ.get('REDIS_NAMESPACE', 'SHORT:')), help='The redis namespace used for all keys') tornado.options.define('redis_password', type=str, default=str(os.environ.get('REDIS_PASSWORD', '')), help='The redis password') tornado.options.define('ttl', type=int, default=int(os.environ.get('TTL', 0)), help='The time to live in days of each link, 0 means forever') # Get logger. access_log = logging.getLogger('tornado.access') # Define application. class Application(tornado.web.Application): """ Main Class for this application holding everything together. It defines the url scheme for the API endpoints, configures application settings, initializes a tornado Application instance and establishes db connections. """ def __init__(self, default_domain='localhost', hash_salt='', redis_namespace='SHORT:', redis_host='localhost', redis_port=6379, redis_db=0, redis_password=None, ttl=0): if not redis_password: redis_password = None using_redis_password = 'NO' else: using_redis_password = 'YES' logging.info( 'Starting application with the following parameters: default_domain: {},' 'hash_salt: {}, redis_namespace: {}, redis_host: {}, redis_port: {},' 'redis_db: {}, redis_password: {}, ttl: {}'.format( default_domain, hash_salt, redis_namespace, redis_host, redis_port, redis_db, using_redis_password, ttl)) # Define routes. handlers = [ (r'/$', IndexHandler), (r'/expand/$', ExpandHandler), (r'/expand', ExpandHandler), (r'/shorten/$', ShortHandler), (r'/shorten$', ShortHandler), (r'/([a-zA-Z0-9]+)/$', RedirectHandler), (r'/([a-zA-Z0-9]+)$', RedirectHandler), ] # Configure application settings. settings = dict( gzip=True, default_domain=default_domain, hash_salt=hash_salt, redis_namespace=redis_namespace, ttl=ttl, template_path=os.path.join(os.path.dirname(__file__), 'templates'), ) # Call super constructor to initiate a Tornado Application. tornado.web.Application.__init__(self, handlers, **settings) # Connect to Redis. self.redis = redis.StrictRedis( host=redis_host, port=redis_port, db=redis_db, password=redis_password, decode_responses=True) def main(): """ Main function to start the webserver application and listen on the specified port. """ tornado.options.parse_command_line() application = Application(tornado.options.options.domain, tornado.options.options.salt, tornado.options.options.redis_namespace, tornado.options.options.redis_host, int(tornado.options.options.redis_port), tornado.options.options.redis_db, tornado.options.options.redis_password, int(tornado.options.options.ttl)) if tornado.options.options.localhostonly: address = '127.0.0.1' logging.info('Listening to localhost only') else: address = '' logging.info('Listening to all addresses on all interfaces') application.listen(tornado.options.options.port, address=address, xheaders=True) tornado.ioloop.IOLoop.instance().start() # Run main method if script is run from command line. if __name__ == '__main__': main()