def __init__(self, options=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = 'TORNADO' self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options self.server = None self.io_loop = None # video root if app.ROOT_DIRS: root_dirs = app.ROOT_DIRS self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: app.WEB_ROOT = self.options['web_root'] = clean_url_path( self.options['web_root']) # Configure root to selected theme. app.WEB_ROOT = self.options['theme_path'] = clean_url_path( app.WEB_ROOT) # Configure the directory to the theme's data root. app.THEME_DATA_ROOT = self.options['theme_data_root'] = os.path.join( self.options['data_root'], app.THEME_NAME) # api root if not app.API_KEY: app.API_KEY = generate_api_key() self.options['api_root'] = r'{root}/api/(?:v1/)?{key}'.format( root=app.WEB_ROOT, key=app.API_KEY) self.options['api_v2_root'] = r'{root}/api/v2'.format( root=app.WEB_ROOT) # websocket root self.options['web_socket'] = r'{root}/ws'.format(root=app.WEB_ROOT) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): log.info( 'Unable to create CERT/KEY files, disabling HTTPS') app.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): log.warning( 'Disabled HTTPS because of missing CERT and KEY files') app.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=True, autoreload=False, gzip=app.WEB_USE_GZIP, xheaders=app.HANDLE_REVERSE_PROXY, cookie_secret=app.WEB_COOKIE_SECRET, login_url=r'{root}/login/'.format(root=self.options['theme_path']), log_function=self.log_request, ) self.app.add_handlers('.*$', get_apiv2_handlers(self.options['api_v2_root'])) # Websocket handler self.app.add_handlers('.*$', [(r'{base}/ui(/?.*)'.format( base=self.options['web_socket']), WebSocketUIHandler)]) # Static File Handlers self.app.add_handlers( '.*$', [ # favicon (r'{base}/favicon\.ico()'.format( base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'assets', 'img', 'ico', 'favicon.ico') }), # images (r'{base}/images/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'assets', 'img') }), # cached images (r'{base}/cache/images/(.*)'.format( base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(app.CACHE_DIR, 'images') }), # css (r'{base}/css/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'assets', 'css') }), # javascript (r'{base}/js/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'assets', 'js') }), # fonts (r'{base}/fonts/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'assets', 'fonts') }), # videos (r'{base}/videos/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, { 'path': self.video_root }), # vue dist (r'{base}/vue/dist/(.*)'.format( base=self.options['theme_path']), StaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'vue') }), # vue index.html (r'{base}/vue/?.*()'.format(base=self.options['theme_path']), AuthenticatedStaticFileHandler, { 'path': os.path.join(self.options['theme_data_root'], 'index.html'), 'default_filename': 'index.html' }), ]) # Used for hot-swapping themes # This is the 2nd rule from the end, because the last one is always `self.app.wildcard_router` self.app.static_file_handlers = self.app.default_router.rules[-2] # API v1 handlers self.app.add_handlers( '.*$', [ # Main handler (r'{base}(/?.*)'.format(base=self.options['api_root']), ApiHandler), # Key retrieval (r'{base}/getkey(/?.*)'.format(base=self.options['web_root']), KeyHandler), # Builder redirect (r'{base}/api/builder'.format(base=self.options['web_root']), RedirectHandler, { 'url': '{base}/apibuilder/'.format(base=self.options['web_root']) }), # Webui login/logout handlers (r'{base}/login(/?)'.format(base=self.options['theme_path']), LoginHandler), (r'{base}/logout(/?)'.format(base=self.options['theme_path']), LogoutHandler), (r'{base}/token(/?)'.format(base=self.options['web_root']), TokenHandler), # Web calendar handler (Needed because option Unprotected calendar) (r'{base}/calendar'.format(base=self.options['web_root']), CalendarHandler), # webui handlers ] + self._get_webui_routes())
def __init__(self, options=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = 'TORNADO' self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options self.server = None self.io_loop = None # video root if app.ROOT_DIRS: root_dirs = app.ROOT_DIRS self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: app.WEB_ROOT = self.options['web_root'] = clean_url_path(self.options['web_root']) # Configure root to selected theme. app.WEB_ROOT = self.options['theme_path'] = clean_url_path(app.WEB_ROOT) # Configure the directory to the theme's data root. app.THEME_DATA_ROOT = self.options['theme_data_root'] = os.path.join(self.options['data_root'], app.THEME_NAME) # api root if not app.API_KEY: app.API_KEY = generate_api_key() self.options['api_root'] = r'{root}/api/(?:v1/)?{key}'.format(root=app.WEB_ROOT, key=app.API_KEY) self.options['api_v2_root'] = r'{root}/api/v2'.format(root=app.WEB_ROOT) # websocket root self.options['web_socket'] = r'{root}/ws'.format(root=app.WEB_ROOT) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): log.info('Unable to create CERT/KEY files, disabling HTTPS') app.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): log.warning('Disabled HTTPS because of missing CERT and KEY files') app.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=True, autoreload=False, gzip=app.WEB_USE_GZIP, xheaders=app.HANDLE_REVERSE_PROXY, cookie_secret=app.WEB_COOKIE_SECRET, login_url=r'{root}/login/'.format(root=self.options['theme_path']), log_function=self.log_request, ) self.app.add_handlers('.*$', get_apiv2_handlers(self.options['api_v2_root'])) # Websocket handler self.app.add_handlers('.*$', [ (r'{base}/ui(/?.*)'.format(base=self.options['web_socket']), WebSocketUIHandler) ]) # Static File Handlers self.app.add_handlers('.*$', [ # favicon (r'{base}/favicon\.ico()'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'assets', 'img', 'ico', 'favicon.ico')}), # images (r'{base}/images/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'assets', 'img')}), # cached images (r'{base}/cache/images/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(app.CACHE_DIR, 'images')}), # css (r'{base}/css/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'assets', 'css')}), # javascript (r'{base}/js/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'assets', 'js')}), # fonts (r'{base}/fonts/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'assets', 'fonts')}), # videos (r'{base}/videos/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': self.video_root}), # vue dist (r'{base}/vue/dist/(.*)'.format(base=self.options['theme_path']), StaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'vue')}), # vue index.html (r'{base}/vue/?.*()'.format(base=self.options['theme_path']), AuthenticatedStaticFileHandler, {'path': os.path.join(self.options['theme_data_root'], 'index.html'), 'default_filename': 'index.html'}), ]) # Used for hot-swapping themes # This is the 2nd rule from the end, because the last one is always `self.app.wildcard_router` self.app.static_file_handlers = self.app.default_router.rules[-2] # API v1 handlers self.app.add_handlers('.*$', [ # Main handler (r'{base}(/?.*)'.format(base=self.options['api_root']), ApiHandler), # Key retrieval (r'{base}/getkey(/?.*)'.format(base=self.options['web_root']), KeyHandler), # Builder redirect (r'{base}/api/builder'.format(base=self.options['web_root']), RedirectHandler, {'url': '{base}/apibuilder/'.format(base=self.options['web_root'])}), # Webui login/logout handlers (r'{base}/login(/?)'.format(base=self.options['theme_path']), LoginHandler), (r'{base}/logout(/?)'.format(base=self.options['theme_path']), LogoutHandler), (r'{base}/token(/?)'.format(base=self.options['web_root']), TokenHandler), # Web calendar handler (Needed because option Unprotected calendar) (r'{base}/calendar'.format(base=self.options['web_root']), CalendarHandler), # webui handlers ] + self._get_webui_routes())