2020-08-12 00:36:09 +00:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import json
|
|
|
|
import asyncio
|
|
|
|
import logging
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
try:
|
|
|
|
import tornado.web
|
|
|
|
import tornado.ioloop
|
|
|
|
import tornado.log
|
|
|
|
import tornado.template
|
|
|
|
import tornado.escape
|
|
|
|
import tornado.locale
|
|
|
|
import tornado.httpserver
|
2022-02-27 17:45:32 +00:00
|
|
|
from app.classes.web.file_handler import FileHandler
|
2020-08-12 00:36:09 +00:00
|
|
|
from app.classes.web.public_handler import PublicHandler
|
2020-08-13 14:38:36 +00:00
|
|
|
from app.classes.web.panel_handler import PanelHandler
|
2020-08-19 17:21:19 +00:00
|
|
|
from app.classes.web.default_handler import DefaultHandler
|
2020-08-19 17:54:10 +00:00
|
|
|
from app.classes.web.server_handler import ServerHandler
|
2020-09-02 01:30:39 +00:00
|
|
|
from app.classes.web.ajax_handler import AjaxHandler
|
2020-09-06 04:58:17 +00:00
|
|
|
from app.classes.web.api_handler import ServersStats, NodeStats
|
2021-03-01 00:54:20 +00:00
|
|
|
from app.classes.web.websocket_handler import SocketHandler
|
2021-04-17 15:12:23 +00:00
|
|
|
from app.classes.web.static_handler import CustomStaticHandler
|
2021-08-22 14:17:33 +00:00
|
|
|
from app.classes.web.upload_handler import UploadHandler
|
2021-08-24 02:25:19 +00:00
|
|
|
from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage
|
2021-08-27 01:06:22 +00:00
|
|
|
from app.classes.web.status_handler import StatusHandler
|
2022-01-26 01:45:30 +00:00
|
|
|
from app.classes.shared.translation import translation
|
|
|
|
from app.classes.shared.console import console
|
|
|
|
from app.classes.shared.helpers import helper
|
2020-08-12 00:36:09 +00:00
|
|
|
|
|
|
|
except ModuleNotFoundError as e:
|
2022-01-26 01:45:30 +00:00
|
|
|
logger.critical(f"Import Error: Unable to load {e.name} module", exc_info=True)
|
|
|
|
console.critical(f"Import Error: Unable to load {e.name} module")
|
2020-08-12 00:36:09 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2021-03-22 04:02:18 +00:00
|
|
|
class Webserver:
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2021-03-22 04:02:18 +00:00
|
|
|
def __init__(self, controller, tasks_manager):
|
2020-08-12 00:36:09 +00:00
|
|
|
self.ioloop = None
|
|
|
|
self.HTTP_Server = None
|
|
|
|
self.HTTPS_Server = None
|
2021-03-22 04:02:18 +00:00
|
|
|
self.controller = controller
|
|
|
|
self.tasks_manager = tasks_manager
|
2020-08-12 00:36:09 +00:00
|
|
|
self._asyncio_patch()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def log_function(handler):
|
|
|
|
|
|
|
|
info = {
|
|
|
|
'Status_Code': handler.get_status(),
|
|
|
|
'Method': handler.request.method,
|
|
|
|
'URL': handler.request.uri,
|
|
|
|
'Remote_IP': handler.request.remote_ip,
|
2022-01-26 01:45:30 +00:00
|
|
|
# pylint: disable=consider-using-f-string
|
2020-08-12 00:36:09 +00:00
|
|
|
'Elapsed_Time': '%.2fms' % (handler.request.request_time() * 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
tornado.log.access_log.info(json.dumps(info, indent=4))
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def _asyncio_patch():
|
|
|
|
"""
|
|
|
|
As of Python 3.8 (on Windows), the asyncio default event handler has changed to "proactor",
|
|
|
|
where tornado expects the "selector" handler.
|
|
|
|
|
|
|
|
This function checks if the platform is windows and changes the event handler to suit.
|
|
|
|
|
|
|
|
(Taken from https://github.com/mkdocs/mkdocs/commit/cf2b136d4257787c0de51eba2d9e30ded5245b31)
|
|
|
|
"""
|
|
|
|
logger.debug("Checking if asyncio patch is required")
|
|
|
|
if sys.platform.startswith("win") and sys.version_info >= (3, 8):
|
2022-01-26 01:45:30 +00:00
|
|
|
# pylint: disable=reimported,import-outside-toplevel,redefined-outer-name
|
2020-08-12 00:36:09 +00:00
|
|
|
import asyncio
|
|
|
|
try:
|
|
|
|
from asyncio import WindowsSelectorEventLoopPolicy
|
|
|
|
except ImportError:
|
2022-01-26 01:45:30 +00:00
|
|
|
logger.debug("asyncio patch isn't required") # Can't assign a policy which doesn't exist.
|
2020-08-12 00:36:09 +00:00
|
|
|
else:
|
|
|
|
if not isinstance(asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy):
|
|
|
|
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
|
|
|
|
logger.debug("Applied asyncio patch")
|
|
|
|
|
|
|
|
def run_tornado(self):
|
|
|
|
|
|
|
|
# let's verify we have an SSL cert
|
|
|
|
helper.create_self_signed_cert()
|
|
|
|
|
2020-08-27 22:30:56 +00:00
|
|
|
http_port = helper.get_setting('http_port')
|
|
|
|
https_port = helper.get_setting('https_port')
|
2022-01-26 01:45:30 +00:00
|
|
|
|
2020-08-27 22:30:56 +00:00
|
|
|
debug_errors = helper.get_setting('show_errors')
|
|
|
|
cookie_secret = helper.get_setting('cookie_secret')
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2020-08-13 01:33:36 +00:00
|
|
|
if cookie_secret is False:
|
|
|
|
cookie_secret = helper.random_string_generator(32)
|
|
|
|
|
2020-08-12 00:36:09 +00:00
|
|
|
if not http_port:
|
2020-08-27 22:30:56 +00:00
|
|
|
http_port = 8000
|
2020-08-12 00:36:09 +00:00
|
|
|
|
|
|
|
if not https_port:
|
2020-08-27 22:30:56 +00:00
|
|
|
https_port = 8443
|
2020-08-12 00:36:09 +00:00
|
|
|
|
|
|
|
cert_objects = {
|
|
|
|
'certfile': os.path.join(helper.config_dir, 'web', 'certs', 'commander.cert.pem'),
|
|
|
|
'keyfile': os.path.join(helper.config_dir, 'web', 'certs', 'commander.key.pem'),
|
|
|
|
}
|
|
|
|
|
2022-01-26 01:45:30 +00:00
|
|
|
logger.info(f"Starting Web Server on ports http:{http_port} https:{https_port}")
|
2020-08-12 00:36:09 +00:00
|
|
|
|
|
|
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
|
|
|
|
|
|
|
tornado.template.Loader('.')
|
|
|
|
|
2022-01-15 15:38:08 +00:00
|
|
|
# TODO: Remove because we don't and won't use
|
2021-09-29 02:25:47 +00:00
|
|
|
tornado.locale.set_default_locale('en_EN')
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2021-03-26 13:57:50 +00:00
|
|
|
handler_args = {"controller": self.controller, "tasks_manager": self.tasks_manager, "translator": translation}
|
2020-08-12 00:36:09 +00:00
|
|
|
handlers = [
|
2021-03-22 04:02:18 +00:00
|
|
|
(r'/', DefaultHandler, handler_args),
|
|
|
|
(r'/public/(.*)', PublicHandler, handler_args),
|
|
|
|
(r'/panel/(.*)', PanelHandler, handler_args),
|
|
|
|
(r'/server/(.*)', ServerHandler, handler_args),
|
|
|
|
(r'/ajax/(.*)', AjaxHandler, handler_args),
|
2022-02-27 17:26:54 +00:00
|
|
|
(r'/files/(.*)', FileHandler, handler_args),
|
2021-03-22 04:02:18 +00:00
|
|
|
(r'/api/stats/servers', ServersStats, handler_args),
|
|
|
|
(r'/api/stats/node', NodeStats, handler_args),
|
|
|
|
(r'/ws', SocketHandler, handler_args),
|
2021-09-25 23:02:05 +00:00
|
|
|
(r'/upload', UploadHandler, handler_args),
|
2021-08-27 01:06:22 +00:00
|
|
|
(r'/status', StatusHandler, handler_args)
|
2020-08-12 00:36:09 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
app = tornado.web.Application(
|
|
|
|
handlers,
|
|
|
|
template_path=os.path.join(helper.webroot, 'templates'),
|
|
|
|
static_path=os.path.join(helper.webroot, 'static'),
|
|
|
|
debug=debug_errors,
|
|
|
|
cookie_secret=cookie_secret,
|
|
|
|
xsrf_cookies=True,
|
|
|
|
autoreload=False,
|
|
|
|
log_function=self.log_function,
|
|
|
|
login_url="/login",
|
2021-04-17 15:12:23 +00:00
|
|
|
default_handler_class=PublicHandler,
|
|
|
|
static_handler_class=CustomStaticHandler,
|
|
|
|
serve_traceback=debug_errors,
|
2020-08-12 00:36:09 +00:00
|
|
|
)
|
2021-08-24 02:25:19 +00:00
|
|
|
HTTPhanders = [(r'/', HTTPHandler, handler_args),
|
|
|
|
(r'/public/(.*)', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/panel/(.*)', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/server/(.*)', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/ajax/(.*)', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/api/stats/servers', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/api/stats/node', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/ws', HTTPHandlerPage, handler_args),
|
|
|
|
(r'/upload', HTTPHandlerPage, handler_args)]
|
|
|
|
HTTPapp = tornado.web.Application(
|
|
|
|
HTTPhanders,
|
|
|
|
template_path=os.path.join(helper.webroot, 'templates'),
|
|
|
|
static_path=os.path.join(helper.webroot, 'static'),
|
|
|
|
debug=debug_errors,
|
|
|
|
cookie_secret=cookie_secret,
|
|
|
|
xsrf_cookies=True,
|
|
|
|
autoreload=False,
|
|
|
|
log_function=self.log_function,
|
|
|
|
default_handler_class = HTTPHandler,
|
|
|
|
login_url="/login",
|
|
|
|
serve_traceback=debug_errors,
|
|
|
|
)
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2021-08-24 02:25:19 +00:00
|
|
|
self.HTTP_Server = tornado.httpserver.HTTPServer(HTTPapp)
|
2020-08-12 00:36:09 +00:00
|
|
|
self.HTTP_Server.listen(http_port)
|
|
|
|
|
|
|
|
self.HTTPS_Server = tornado.httpserver.HTTPServer(app, ssl_options=cert_objects)
|
|
|
|
self.HTTPS_Server.listen(https_port)
|
|
|
|
|
2022-01-26 01:45:30 +00:00
|
|
|
logger.info(f"https://{helper.get_local_ip()}:{https_port} is up and ready for connections.")
|
|
|
|
console.info(f"https://{helper.get_local_ip()}:{https_port} is up and ready for connections.")
|
2021-05-02 15:15:19 +00:00
|
|
|
|
2020-08-12 00:36:09 +00:00
|
|
|
console.info("Server Init Complete: Listening For Connections:")
|
|
|
|
|
2021-08-11 20:29:31 +00:00
|
|
|
self.ioloop = tornado.ioloop.IOLoop.current()
|
2020-08-12 00:36:09 +00:00
|
|
|
self.ioloop.start()
|
|
|
|
|
|
|
|
def stop_web_server(self):
|
|
|
|
logger.info("Shutting Down Web Server")
|
|
|
|
console.info("Shutting Down Web Server")
|
|
|
|
self.ioloop.stop()
|
|
|
|
self.HTTP_Server.stop()
|
|
|
|
self.HTTPS_Server.stop()
|
|
|
|
logger.info("Web Server Stopped")
|
|
|
|
console.info("Web Server Stopped")
|