2020-08-12 00:36:09 +00:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import json
|
|
|
|
import asyncio
|
|
|
|
import logging
|
2022-04-11 05:23:55 +00:00
|
|
|
import tornado.web
|
|
|
|
import tornado.ioloop
|
|
|
|
import tornado.log
|
|
|
|
import tornado.template
|
|
|
|
import tornado.escape
|
|
|
|
import tornado.locale
|
|
|
|
import tornado.httpserver
|
|
|
|
|
2022-04-12 01:34:46 +00:00
|
|
|
from app.classes.shared.console import Console
|
2022-04-11 05:23:55 +00:00
|
|
|
from app.classes.shared.helpers import Helpers
|
2022-05-05 00:32:09 +00:00
|
|
|
from app.classes.shared.main_controller import Controller
|
2022-03-08 04:40:44 +00:00
|
|
|
from app.classes.web.file_handler import FileHandler
|
|
|
|
from app.classes.web.public_handler import PublicHandler
|
|
|
|
from app.classes.web.panel_handler import PanelHandler
|
|
|
|
from app.classes.web.default_handler import DefaultHandler
|
2022-04-14 12:33:53 +00:00
|
|
|
from app.classes.web.routes.api.api_handlers import api_handlers
|
2022-03-08 04:40:44 +00:00
|
|
|
from app.classes.web.server_handler import ServerHandler
|
|
|
|
from app.classes.web.ajax_handler import AjaxHandler
|
2022-04-10 19:39:31 +00:00
|
|
|
from app.classes.web.api_handler import (
|
|
|
|
ServersStats,
|
|
|
|
NodeStats,
|
|
|
|
ServerBackup,
|
|
|
|
StartServer,
|
|
|
|
StopServer,
|
|
|
|
RestartServer,
|
|
|
|
CreateUser,
|
|
|
|
DeleteUser,
|
|
|
|
ListServers,
|
|
|
|
SendCommand,
|
|
|
|
)
|
2022-03-08 04:40:44 +00:00
|
|
|
from app.classes.web.websocket_handler import SocketHandler
|
|
|
|
from app.classes.web.static_handler import CustomStaticHandler
|
|
|
|
from app.classes.web.upload_handler import UploadHandler
|
|
|
|
from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage
|
|
|
|
from app.classes.web.status_handler import StatusHandler
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-03-08 04:40:44 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
2020-08-12 00:36:09 +00:00
|
|
|
|
|
|
|
|
2022-03-23 02:50:12 +00:00
|
|
|
class Webserver:
|
2022-05-05 00:32:09 +00:00
|
|
|
controller: Controller
|
|
|
|
helper: Helpers
|
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
def __init__(self, helper, controller, tasks_manager):
|
2020-08-12 00:36:09 +00:00
|
|
|
self.ioloop = None
|
2022-04-14 02:10:25 +00:00
|
|
|
self.http_server = None
|
|
|
|
self.https_server = None
|
2022-04-11 05:23:55 +00:00
|
|
|
self.helper = helper
|
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 = {
|
2022-03-23 02:50:12 +00:00
|
|
|
"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
|
2022-03-23 02:50:12 +00:00
|
|
|
"Elapsed_Time": "%.2fms" % (handler.request.request_time() * 1000),
|
2020-08-12 00:36:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tornado.log.access_log.info(json.dumps(info, indent=4))
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def _asyncio_patch():
|
|
|
|
"""
|
2022-03-23 06:06:13 +00:00
|
|
|
As of Python 3.8 (on Windows),
|
|
|
|
the asyncio default event handler has changed to "proactor",
|
2020-08-12 00:36:09 +00:00
|
|
|
where tornado expects the "selector" handler.
|
|
|
|
|
2022-03-23 06:06:13 +00:00
|
|
|
This function checks if the platform is windows and
|
|
|
|
changes the event handler to suit.
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-03-23 06:06:13 +00:00
|
|
|
(Taken from
|
|
|
|
https://github.com/mkdocs/mkdocs/commit/cf2b136d4257787c0de51eba2d9e30ded5245b31)
|
2020-08-12 00:36:09 +00:00
|
|
|
"""
|
|
|
|
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
|
2022-03-23 02:50:12 +00:00
|
|
|
|
2020-08-12 00:36:09 +00:00
|
|
|
try:
|
|
|
|
from asyncio import WindowsSelectorEventLoopPolicy
|
|
|
|
except ImportError:
|
2022-03-23 02:50:12 +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:
|
2022-03-23 02:50:12 +00:00
|
|
|
if not isinstance(
|
|
|
|
asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy
|
|
|
|
):
|
2020-08-12 00:36:09 +00:00
|
|
|
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
|
|
|
|
logger.debug("Applied asyncio patch")
|
|
|
|
|
|
|
|
def run_tornado(self):
|
|
|
|
|
|
|
|
# let's verify we have an SSL cert
|
2022-04-11 05:23:55 +00:00
|
|
|
self.helper.create_self_signed_cert()
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
http_port = self.helper.get_setting("http_port")
|
|
|
|
https_port = self.helper.get_setting("https_port")
|
2022-01-26 01:45:30 +00:00
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
debug_errors = self.helper.get_setting("show_errors")
|
|
|
|
cookie_secret = self.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:
|
2022-04-11 05:23:55 +00:00
|
|
|
cookie_secret = self.helper.random_string_generator(32)
|
2020-08-13 01:33:36 +00:00
|
|
|
|
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 = {
|
2022-03-23 02:50:12 +00:00
|
|
|
"certfile": os.path.join(
|
2022-04-11 05:23:55 +00:00
|
|
|
self.helper.config_dir, "web", "certs", "commander.cert.pem"
|
2022-03-23 02:50:12 +00:00
|
|
|
),
|
|
|
|
"keyfile": os.path.join(
|
2022-04-11 05:23:55 +00:00
|
|
|
self.helper.config_dir, "web", "certs", "commander.key.pem"
|
2022-03-23 02:50:12 +00:00
|
|
|
),
|
2020-08-12 00:36:09 +00:00
|
|
|
}
|
|
|
|
|
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())
|
|
|
|
|
2022-03-23 02:50:12 +00:00
|
|
|
tornado.template.Loader(".")
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-01-15 15:38:08 +00:00
|
|
|
# TODO: Remove because we don't and won't use
|
2022-03-23 02:50:12 +00:00
|
|
|
tornado.locale.set_default_locale("en_EN")
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-03-23 02:50:12 +00:00
|
|
|
handler_args = {
|
2022-04-11 05:23:55 +00:00
|
|
|
"helper": self.helper,
|
2022-03-23 02:50:12 +00:00
|
|
|
"controller": self.controller,
|
|
|
|
"tasks_manager": self.tasks_manager,
|
2022-04-11 05:23:55 +00:00
|
|
|
"translator": self.helper.translation,
|
2022-03-23 02:50:12 +00:00
|
|
|
}
|
2020-08-12 00:36:09 +00:00
|
|
|
handlers = [
|
2022-03-23 02:50:12 +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),
|
|
|
|
(r"/files/(.*)", FileHandler, handler_args),
|
|
|
|
(r"/ws", SocketHandler, handler_args),
|
|
|
|
(r"/upload", UploadHandler, handler_args),
|
|
|
|
(r"/status", StatusHandler, handler_args),
|
2022-04-14 12:33:53 +00:00
|
|
|
# API Routes V1
|
2022-04-10 19:39:31 +00:00
|
|
|
(r"/api/v1/stats/servers", ServersStats, handler_args),
|
|
|
|
(r"/api/v1/stats/node", NodeStats, handler_args),
|
|
|
|
(r"/api/v1/server/send_command", SendCommand, handler_args),
|
|
|
|
(r"/api/v1/server/backup", ServerBackup, handler_args),
|
|
|
|
(r"/api/v1/server/start", StartServer, handler_args),
|
|
|
|
(r"/api/v1/server/stop", StopServer, handler_args),
|
|
|
|
(r"/api/v1/server/restart", RestartServer, handler_args),
|
|
|
|
(r"/api/v1/list_servers", ListServers, handler_args),
|
|
|
|
(r"/api/v1/users/create_user", CreateUser, handler_args),
|
|
|
|
(r"/api/v1/users/delete_user", DeleteUser, handler_args),
|
2022-04-14 12:33:53 +00:00
|
|
|
# API Routes V2
|
|
|
|
*api_handlers(handler_args),
|
2022-03-23 02:50:12 +00:00
|
|
|
]
|
2020-08-12 00:36:09 +00:00
|
|
|
|
|
|
|
app = tornado.web.Application(
|
|
|
|
handlers,
|
2022-04-11 05:23:55 +00:00
|
|
|
template_path=os.path.join(self.helper.webroot, "templates"),
|
|
|
|
static_path=os.path.join(self.helper.webroot, "static"),
|
2020-08-12 00:36:09 +00:00
|
|
|
debug=debug_errors,
|
|
|
|
cookie_secret=cookie_secret,
|
|
|
|
xsrf_cookies=True,
|
|
|
|
autoreload=False,
|
|
|
|
log_function=self.log_function,
|
2022-06-08 19:42:25 +00:00
|
|
|
login_url="/public/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
|
|
|
)
|
2022-04-14 02:10:25 +00:00
|
|
|
http_handers = [
|
2022-03-23 02:50:12 +00:00
|
|
|
(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),
|
|
|
|
]
|
2022-04-14 02:10:25 +00:00
|
|
|
http_app = tornado.web.Application(
|
|
|
|
http_handers,
|
2022-04-11 05:23:55 +00:00
|
|
|
template_path=os.path.join(self.helper.webroot, "templates"),
|
|
|
|
static_path=os.path.join(self.helper.webroot, "static"),
|
2021-08-24 02:25:19 +00:00
|
|
|
debug=debug_errors,
|
|
|
|
cookie_secret=cookie_secret,
|
|
|
|
xsrf_cookies=True,
|
|
|
|
autoreload=False,
|
|
|
|
log_function=self.log_function,
|
2022-03-23 02:50:12 +00:00
|
|
|
default_handler_class=HTTPHandler,
|
2022-06-08 19:42:25 +00:00
|
|
|
login_url="/public/login",
|
2021-08-24 02:25:19 +00:00
|
|
|
serve_traceback=debug_errors,
|
|
|
|
)
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-04-14 02:10:25 +00:00
|
|
|
self.http_server = tornado.httpserver.HTTPServer(http_app)
|
|
|
|
self.http_server.listen(http_port)
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-04-14 02:10:25 +00:00
|
|
|
self.https_server = tornado.httpserver.HTTPServer(app, ssl_options=cert_objects)
|
|
|
|
self.https_server.listen(https_port)
|
2020-08-12 00:36:09 +00:00
|
|
|
|
2022-03-23 02:50:12 +00:00
|
|
|
logger.info(
|
2022-04-11 05:23:55 +00:00
|
|
|
f"https://{Helpers.get_local_ip()}:{https_port} "
|
2022-03-23 06:06:13 +00:00
|
|
|
f"is up and ready for connections."
|
2022-03-23 02:50:12 +00:00
|
|
|
)
|
2022-04-12 01:34:46 +00:00
|
|
|
Console.info(
|
2022-04-11 05:23:55 +00:00
|
|
|
f"https://{Helpers.get_local_ip()}:{https_port} "
|
2022-03-23 06:06:13 +00:00
|
|
|
f"is up and ready for connections."
|
2022-03-23 02:50:12 +00:00
|
|
|
)
|
2021-05-02 15:15:19 +00:00
|
|
|
|
2022-05-20 21:00:21 +00:00
|
|
|
Console.info("Server Init Complete: Listening For Connections!")
|
2020-08-12 00:36:09 +00:00
|
|
|
|
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")
|
2022-04-12 01:34:46 +00:00
|
|
|
Console.info("Shutting Down Web Server")
|
2020-08-12 00:36:09 +00:00
|
|
|
self.ioloop.stop()
|
2022-04-14 02:10:25 +00:00
|
|
|
self.http_server.stop()
|
|
|
|
self.https_server.stop()
|
2020-08-12 00:36:09 +00:00
|
|
|
logger.info("Web Server Stopped")
|
2022-04-12 01:34:46 +00:00
|
|
|
Console.info("Web Server Stopped")
|