同步操作将从 mirrors_bugy/script-server 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
#!/usr/bin/env python3import asyncioimport jsonimport logging.configimport osimport signalimport sslimport timeimport urllibfrom urllib.parse import urlencodeimport tornado.concurrentimport tornado.escapeimport tornado.httpserver as httpserverimport tornado.ioloopimport tornado.routingimport tornado.webimport tornado.websocketfrom auth.identification import AuthBasedIdentification, IpBasedIdentificationfrom auth.tornado_auth import TornadoAuthfrom communications.alerts_service import AlertsServicefrom config.config_service import ConfigService, ConfigNotAllowedException, InvalidAccessException, \CorruptConfigFileExceptionfrom config.exceptions import InvalidConfigExceptionfrom execution.execution_service import ExecutionServicefrom execution.logging import ExecutionLoggingServicefrom features.file_download_feature import FileDownloadFeaturefrom features.file_upload_feature import FileUploadFeaturefrom model import external_modelfrom model.external_model import to_short_execution_log, to_long_execution_logfrom model.model_helper import is_empty, InvalidFileException, AccessProhibitedExceptionfrom model.parameter_config import WrongParameterUsageExceptionfrom model.script_config import InvalidValueException, ParameterNotFoundExceptionfrom model.server_conf import ServerConfig, XSRF_PROTECTION_TOKEN, XSRF_PROTECTION_DISABLED, XSRF_PROTECTION_HEADERfrom scheduling.schedule_service import ScheduleService, UnavailableScriptException, InvalidScheduleExceptionfrom utils import file_utils as file_utilsfrom utils import tornado_utils, os_utils, env_utils, custom_jsonfrom utils.audit_utils import get_audit_name_from_requestfrom utils.exceptions.missing_arg_exception import MissingArgumentExceptionfrom utils.exceptions.not_found_exception import NotFoundExceptionfrom utils.tornado_utils import respond_error, redirect_relative, get_form_filefrom web.script_config_socket import ScriptConfigSocket, active_config_modelsfrom web.streaming_form_reader import StreamingFormReaderfrom web.web_auth_utils import check_authorization, check_authorization_syncfrom web.web_utils import wrap_to_server_event, identify_user, inject_user, get_userfrom web.xheader_app_wrapper import autoapply_xheadersBYTES_IN_MB = 1024 * 1024LOGGER = logging.getLogger('web_server')def requires_admin_rights(func):def wrapper(self, *args, **kwargs):if not has_admin_rights(self):user_id = identify_user(self)LOGGER.warning('User %s (%s) tried to access admin REST service %s',user_id, get_audit_name_from_request(self), self.request.path)raise tornado.web.HTTPError(403, 'Access denied')return func(self, *args, **kwargs)return wrapperdef has_admin_rights(request_handler):user_id = identify_user(request_handler)return request_handler.application.authorizer.is_admin(user_id)class ProxiedRedirectHandler(tornado.web.RedirectHandler):def get(self, *args):redirect_relative(self._url.format(*args), self, *args)def exception_to_code_and_message(exception):if isinstance(exception, AccessProhibitedException):return 403, str(exception)if isinstance(exception, MissingArgumentException):return 400, str(exception)if isinstance(exception, NotFoundException):return 404, str(exception)return None, Noneclass BaseRequestHandler(tornado.web.RequestHandler):def set_default_headers(self):self.set_header('X-Frame-Options', 'DENY')if self.application.server_config.xsrf_protection == XSRF_PROTECTION_TOKEN:# This is needed to initialize cookie (by default tornado does it only on html template rendering)# noinspection PyStatementEffectself.xsrf_tokendef check_xsrf_cookie(self):xsrf_protection = self.application.server_config.xsrf_protectionif xsrf_protection == XSRF_PROTECTION_TOKEN:return super().check_xsrf_cookie()elif xsrf_protection == XSRF_PROTECTION_HEADER:requested_with = self.request.headers.get('X-Requested-With')if not requested_with:raise tornado.web.HTTPError(403, 'X-Requested-With header is missing for XSRF protection')returndef write_error(self, status_code, **kwargs):if ('exc_info' in kwargs) and (kwargs['exc_info']):(type, value, traceback) = kwargs['exc_info'](custom_code, custom_message) = exception_to_code_and_message(value)if custom_code:respond_error(self, custom_code, custom_message)returnrespond_error(self, status_code, self._reason)class BaseStaticHandler(tornado.web.StaticFileHandler):def set_default_headers(self):self.set_header('X-Frame-Options', 'DENY')class GetServerConf(BaseRequestHandler):@check_authorizationdef get(self):self.write(external_model.server_conf_to_external(self.application.server_config,self.application.server_version))class GetScripts(BaseRequestHandler):@check_authorization@inject_userdef get(self, user):mode = self.get_query_argument('mode', default=None)configs = self.application.config_service.list_configs(user, mode)scripts = [{'name': conf.name, 'group': conf.group, 'parsing_failed': conf.parsing_failed} for conf in configs]self.write(json.dumps({'scripts': scripts}))class AdminUpdateScriptEndpoint(BaseRequestHandler):@requires_admin_rights@inject_userdef post(self, user):(config, _, uploaded_script) = self.read_config_parameters()try:self.application.config_service.create_config(user, config, uploaded_script)except InvalidConfigException as e:logging.warning('Failed to create script config', exc_info=True)raise tornado.web.HTTPError(422, reason=str(e))except InvalidAccessException as e:logging.warning('Failed to create script config', exc_info=True)raise tornado.web.HTTPError(403, reason=str(e))@requires_admin_rights@inject_userdef put(self, user):(config, filename, uploaded_script) = self.read_config_parameters()try:self.application.config_service.update_config(user, config, filename, uploaded_script)except (InvalidConfigException, InvalidFileException) as e:raise tornado.web.HTTPError(422, str(e))except ConfigNotAllowedException:LOGGER.warning('Admin access to the script "' + config['name'] + '" is denied for ' + user.get_audit_name())respond_error(self, 403, 'Access to the script is denied')returnexcept InvalidAccessException as e:raise tornado.web.HTTPError(403, reason=str(e))def read_config_parameters(self):config = json.loads(self.get_argument('config'))filename = self.get_argument('filename', default=None)uploaded_script = get_form_file(self, 'uploadedScript')return config, filename, uploaded_scriptclass AdminScriptEndpoint(BaseRequestHandler):@requires_admin_rights@inject_userdef get(self, user, script_name):try:config = self.application.config_service.load_config(script_name, user)except ConfigNotAllowedException:LOGGER.warning('Admin access to the script "' + script_name + '" is denied for ' + user.get_audit_name())respond_error(self, 403, 'Access to the script is denied')returnexcept CorruptConfigFileException as e:respond_error(self, CorruptConfigFileException.HTTP_CODE, str(e))returnif config is None:raise tornado.web.HTTPError(404, str('Failed to find config for name: ' + script_name))self.write(json.dumps(config))@requires_admin_rights@inject_userdef delete(self, user, script_name):try:self.application.config_service.delete_config(user, script_name)except ConfigNotAllowedException:LOGGER.warning(f'Admin access to the script "{script_name}" is denied for {user.get_audit_name()}')respond_error(self, 403, 'Access to the script is denied')returnexcept NotFoundException as e:LOGGER.warning(f'Failed to delete script {script_name}', exc_info=True)respond_error(self, 404, str(e))returnexcept InvalidAccessException as e:raise tornado.web.HTTPError(403, reason=str(e)) from eclass AdminGetScriptCodeEndpoint(BaseRequestHandler):@requires_admin_rights@inject_userdef get(self, user, script_name):try:loaded_script = self.application.config_service.load_script_code(script_name, user)except ConfigNotAllowedException:LOGGER.warning('Admin access to the script "' + script_name + '" is denied for ' + user.get_audit_name())respond_error(self, 403, 'Access to the script is denied')returnexcept InvalidFileException as e:LOGGER.warning('Failed to load script code for script ' + script_name, exc_info=True)respond_error(self, 422, str(e))returnexcept InvalidAccessException as e:raise tornado.web.HTTPError(403, reason=str(e))if loaded_script is None:raise tornado.web.HTTPError(404, str('Failed to find config for name: ' + script_name))self.write(json.dumps(loaded_script))class ScriptStop(BaseRequestHandler):@check_authorization@inject_userdef post(self, user, execution_id):self.application.execution_service.stop_script(execution_id, user)class ScriptKill(BaseRequestHandler):@check_authorization@inject_userdef post(self, user, execution_id):self.application.execution_service.kill_script(execution_id, user)class ScriptStreamSocket(tornado.websocket.WebSocketHandler):def __init__(self, application, request, **kwargs):super().__init__(application, request, **kwargs)self.executor = None@check_authorization@inject_userdef open(self, user, execution_id):execution_service = self.application.execution_servicetry:self.executor = execution_service.get_active_executor(execution_id, get_user(self))except Exception as e:self.handle_exception_on_open(e)returnself.ioloop = tornado.ioloop.IOLoop.current()self.write_message(wrap_to_server_event('input', 'your input >>'))user_id = identify_user(self)output_stream = execution_service.get_raw_output_stream(execution_id, user_id)pipe_output_to_http(output_stream, self.safe_write)file_download_feature = self.application.file_download_featureweb_socket = selfdef finished():try:downloadable_files = file_download_feature.get_downloadable_files(execution_id)for file in downloadable_files:filename = os.path.basename(file)url_path = web_socket.prepare_download_url(file)web_socket.safe_write(wrap_to_server_event('file',{'url': url_path, 'filename': filename}))except:LOGGER.exception('Could not prepare downloadable files')connection = web_socket.ws_connectionif (connection is not None) and (hasattr(connection, 'ping_callback')):# we need to stop callback explicitly and as soon as possible, to avoid sending ping after closeconnection.ping_callback.stop()output_stream.wait_close(timeout=5)web_socket.ioloop.add_callback(web_socket.close, code=1000)file_download_feature.subscribe_on_inline_images(execution_id, self.send_inline_image)execution_service.add_finish_listener(finished, execution_id)def on_message(self, text):self.executor.write_to_input(text)def on_close(self):audit_name = get_audit_name_from_request(self)LOGGER.info(audit_name + ' disconnected')def safe_write(self, message):if self.ws_connection is not None:self.ioloop.add_callback(self.write_message, message)def send_inline_image(self, original_path, download_path):self.safe_write(wrap_to_server_event('inline-image',{'output_path': original_path, 'download_url': self.prepare_download_url(download_path)}))def prepare_download_url(self, file):downloads_folder = self.application.downloads_folderrelative_path = file_utils.relative_path(file, downloads_folder)filename = tornado.escape.url_escape(os.path.basename(relative_path))relative_dir = os.path.dirname(relative_path).replace(os.path.sep, '/')url_path = relative_dir + '/' + filenamereturn 'result_files/' + url_pathdef handle_exception_on_open(self, e):(status_code, message) = exception_to_code_and_message(e)if status_code:self.close(code=status_code, reason=message)returnraise e@tornado.web.stream_request_bodyclass StreamUploadRequestHandler(BaseRequestHandler):def __init__(self, application, request, **kwargs):super().__init__(application, request, **kwargs)self.form_reader = None@check_authorizationdef prepare(self):if self.request.method != 'POST':respond_error(self, 405, 'Method not allowed')returnaudit_name = get_audit_name_from_request(self)file_upload_feature = self.application.file_upload_featureupload_folder = file_upload_feature.prepare_new_folder(audit_name)self.request.connection.set_max_body_size(self.application.max_request_size_mb * BYTES_IN_MB)self.form_reader = StreamingFormReader(self.request.headers, upload_folder)def data_received(self, chunk):self.form_reader.read(chunk)class ScriptExecute(StreamUploadRequestHandler):def __init__(self, application, request, **kwargs):super().__init__(application, request, **kwargs)@inject_userdef post(self, user):script_name = Noneaudit_name = user.get_audit_name()try:arguments = self.form_reader.valuesexecution_info = external_model.to_execution_info(arguments)script_name = execution_info.scriptconfig_model = self.application.config_service.load_config_model(script_name, user)if not config_model:message = 'Script with name "' + str(script_name) + '" not found'LOGGER.error(message)respond_error(self, 400, message)returnparameter_values = execution_info.param_valuesif self.form_reader.files:for key, value in self.form_reader.files.items():parameter_values[key] = value.pathall_audit_names = user.audit_namesLOGGER.info('Calling script %s. User %s', script_name, all_audit_names)config_model.set_all_param_values(parameter_values)execution_id = self.application.execution_service.start_script(config_model, user)self.write(str(execution_id))except InvalidValueException as e:message = 'Invalid parameter %s value: %s' % (e.param_name, str(e))LOGGER.error(message)respond_error(self, 422, message)returnexcept ConfigNotAllowedException:LOGGER.warning('Access to the script "' + script_name + '" is denied for ' + audit_name)respond_error(self, 403, 'Access to the script is denied')returnexcept CorruptConfigFileException as e:respond_error(self, CorruptConfigFileException.HTTP_CODE, str(e))return Noneexcept Exception as e:LOGGER.exception("Error while calling the script")if hasattr(e, "strerror") and e.strerror:error_output = e.strerrorelse:error_output = "Unknown error occurred, contact the administrator"result = " --- ERRORS --- \n"result += error_outputif script_name:script = str(script_name)else:script = "Some script"audit_name = audit_nameself.application.alerts_service.send_alert(script + ' NOT STARTED',"Couldn't start the script " + script + ' by ' + audit_name + '.\n\n'+ result)respond_error(self, 500, result)class GetActiveExecutionIds(BaseRequestHandler):@check_authorizationdef get(self):user_id = identify_user(self)execution_service = self.application.execution_serviceactive_executions = execution_service.get_active_executions(user_id)self.write(json.dumps(active_executions))class GetExecutingScriptConfig(BaseRequestHandler):@check_authorization@inject_userdef get(self, user, execution_id):config = self.application.execution_service.get_config(execution_id, user)values = dict(self.application.execution_service.get_user_parameter_values(execution_id))for parameter in config.parameters:parameter_name = parameter.nameif (parameter_name in values) and (parameter.type == 'file_upload'):del values[parameter_name]self.write({'scriptName': config.name,'parameterValues': values})class CleanupExecutingScript(BaseRequestHandler):@check_authorization@inject_userdef post(self, user, execution_id):self.application.execution_service.cleanup_execution(execution_id, user)class GetExecutionStatus(BaseRequestHandler):@check_authorization@inject_userdef get(self, user, execution_id):running = self.application.execution_service.is_running(execution_id, user)self.write(external_model.running_flag_to_status(running))class AuthorizedStaticFileHandler(BaseStaticHandler):admin_files = ['admin.html', 'css/admin.css', 'admin.js', 'admin-deps.css']@check_authorization_syncdef validate_absolute_path(self, root, absolute_path):if not self.application.auth.is_enabled() and (absolute_path.endswith("/login.html")):raise tornado.web.HTTPError(404)relative_path = file_utils.relative_path(absolute_path, root)if self.is_admin_file(relative_path):if not has_admin_rights(self):user_id = identify_user(self)LOGGER.warning('User %s (%s) tried to access admin static file %s',user_id, get_audit_name_from_request(self), relative_path)raise tornado.web.HTTPError(403)return super(AuthorizedStaticFileHandler, self).validate_absolute_path(root, absolute_path)@classmethoddef get_absolute_path(cls, root, path):path = path.lstrip('/')return super().get_absolute_path(root, path)def is_admin_file(self, relative_path):for admin_file in self.admin_files:if admin_file.endswith('*'):if relative_path.startswith(admin_file[:-1]):return Trueelif relative_path == admin_file:return Truereturn Falseclass ThemeStaticFileHandler(AuthorizedStaticFileHandler):async def get(self, path: str, include_body: bool = True) -> None:if path == 'theme.css':self.absolute_path = self.get_absolute_path(self.root, path)if not os.path.exists(self.absolute_path):# if custom theme doesn't exist, return empty bodyreturnreturn await super().get(path, include_body)class ScriptParameterListFiles(BaseRequestHandler):@check_authorization@inject_userdef get(self, user, script_name, parameter_name):id = self.get_query_argument('id')if not id:respond_error(self, 400, 'Model id is not specified')returnif id not in active_config_models:respond_error(self, 400, 'Model with id=' + str(id) + ' does not exist')returnactive_model = active_config_models[id]config_user_id = active_model['user_id']if config_user_id != user.user_id:LOGGER.warning('User ' + str(user) + ' tried to access config '+ script_name + ' of user #' + config_user_id)respond_error(self, 400, 'Model with id=' + str(id) + ' does not exist')returnconfig_model = active_model['model']if config_model.name != script_name:LOGGER.warning('Config name differences for #' + str(id) + '. Expected ' + config_model.name + ', got ' + script_name)respond_error(self, 500, 'Failed to load script by name')returnpath = self.get_query_arguments('path')try:files = config_model.list_files_for_param(parameter_name, path)self.write(json.dumps(files))except ParameterNotFoundException as e:respond_error(self, 404, 'Parameter ' + e.param_name + ' does not exist')returnexcept (InvalidValueException, WrongParameterUsageException) as e:respond_error(self, 400, str(e))returnclass LoginHandler(BaseRequestHandler):def post(self):auth = self.application.authreturn auth.authenticate(self)class AuthInfoHandler(BaseRequestHandler):@check_authorization@inject_userdef get(self, user):auth = self.application.authauthorizer = self.application.authorizerusername = Noneif auth.is_enabled():username = auth.get_username(self)try:admin_rights = has_admin_rights(self)except Exception:admin_rights = Falseinfo = {'enabled': auth.is_enabled(),'username': username,'admin': admin_rights,'canEditCode': authorizer.can_edit_code(user.user_id)}self.write(info)class AuthConfigHandler(BaseRequestHandler):def get(self):auth = self.application.authif not auth.is_enabled():raise tornado.web.HTTPError(404)self.write(auth.get_client_visible_config())class LogoutHandler(BaseRequestHandler):@check_authorizationdef post(self):auth = self.application.authauth.logout(self)class DownloadResultFile(AuthorizedStaticFileHandler):def set_extra_headers(self, path):super().set_extra_headers(path)filename = os.path.basename(path)encoded_filename = urllib.parse.quote(filename, encoding='utf-8')self.set_header('Content-Disposition', 'attachment; filename*=UTF-8\'\'' + encoded_filename + '')@check_authorization_syncdef validate_absolute_path(self, root, absolute_path):audit_name = get_audit_name_from_request(self)user_id = identify_user(self)file_download_feature = self.application.file_download_featurefile_path = file_utils.relative_path(absolute_path, os.path.abspath(root))if not file_download_feature.allowed_to_download(file_path, user_id):LOGGER.warning('Access attempt from ' + user_id + '(' + audit_name + ') to ' + absolute_path)raise tornado.web.HTTPError(403)return super(AuthorizedStaticFileHandler, self).validate_absolute_path(root, absolute_path)# Use for testing onlyclass ReceiveAlertHandler(BaseRequestHandler):def post(self):body = tornado_utils.get_request_body(self)files = body.get('files', {})if files:del body['files']LOGGER.info('ReceiveAlertHandler. Received alert: ' + str(body))for key, value in files.items():filename = str(time.time()) + '_' + keyLOGGER.info('ReceiveAlertHandler. Writing file ' + filename)file_path = os.path.join('logs', 'alerts', filename)file_utils.write_file(file_path, value)class GetShortHistoryEntriesHandler(BaseRequestHandler):@check_authorization@inject_userdef get(self, user):history_entries = self.application.execution_logging_service.get_history_entries(user.user_id)running_script_ids = []for entry in history_entries:if self.application.execution_service.is_running(entry.id, user):running_script_ids.append(entry.id)short_logs = to_short_execution_log(history_entries, running_script_ids)self.write(json.dumps(short_logs))class GetLongHistoryEntryHandler(BaseRequestHandler):@check_authorization@inject_userdef get(self, user, execution_id):if is_empty(execution_id):respond_error(self, 400, 'Execution id is not specified')returntry:history_entry = self.application.execution_logging_service.find_history_entry(execution_id, user.user_id)except AccessProhibitedException:respond_error(self, 403, 'Access to execution #' + str(execution_id) + ' is prohibited')returnif history_entry is None:respond_error(self, 400, 'No history found for id ' + execution_id)returnlog = self.application.execution_logging_service.find_log(execution_id)if is_empty(log):LOGGER.warning('No log found for execution ' + execution_id)running = self.application.execution_service.is_running(history_entry.id, user)long_log = to_long_execution_log(history_entry, log, running)self.write(json.dumps(long_log))@tornado.web.stream_request_bodyclass AddSchedule(StreamUploadRequestHandler):def __init__(self, application, request, **kwargs):super().__init__(application, request, **kwargs)@inject_userdef post(self, user):arguments = self.form_reader.valuesexecution_info = external_model.to_execution_info(arguments)parameter_values = execution_info.param_valuesif self.form_reader.files:for key, value in self.form_reader.files.items():parameter_values[key] = value.pathschedule_config = custom_json.loads(parameter_values['__schedule_config'])del parameter_values['__schedule_config']try:id = self.application.schedule_service.create_job(execution_info.script,parameter_values,external_model.parse_external_schedule(schedule_config),user)except (UnavailableScriptException, InvalidScheduleException) as e:raise tornado.web.HTTPError(422, reason=str(e))except InvalidValueException as e:raise tornado.web.HTTPError(422, reason=e.get_user_message())self.write(json.dumps({'id': id}))def pipe_output_to_http(output_stream, write_callback):class OutputToHttpListener:def on_next(self, output):write_callback(wrap_to_server_event('output', output))def on_close(self):passoutput_stream.subscribe(OutputToHttpListener())def intercept_stop_when_running_scripts(io_loop, execution_service):def signal_handler(signum, frame):can_stop = Truerunning_processes = execution_service.get_running_executions()if len(running_processes) > 0:try:user_input = input('Some scripts are still running. Do you want to stop server anyway? Y/N: \n')can_stop = (user_input.strip().lower()[0] == 'y')except EOFError:# EOF happens, when input is not available (e.g. when run under systemd)LOGGER.warning('Some scripts are still running, killing them forcefully')can_stop = Trueif can_stop:try:LOGGER.info('Killing the running processes: ' + str(running_processes))for id in running_processes:execution_service.kill_script_by_system(id)except:LOGGER.exception('Could not kill running scripts, trying to stop the server')if can_stop:LOGGER.info('Stopping server on interrupt')io_loop.add_callback_from_signal(io_loop.stop)signal.signal(signal.SIGINT, signal_handler)_http_server = Nonedef init(server_config: ServerConfig,authenticator,authorizer,execution_service: ExecutionService,schedule_service: ScheduleService,execution_logging_service: ExecutionLoggingService,config_service: ConfigService,alerts_service: AlertsService,file_upload_feature: FileUploadFeature,file_download_feature: FileDownloadFeature,secret,server_version,conf_folder,*,start_server=True):ssl_context = Noneif server_config.is_ssl():ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)ssl_context.load_cert_chain(server_config.get_ssl_cert_path(),server_config.get_ssl_key_path())auth = TornadoAuth(authenticator)if auth.is_enabled():identification = AuthBasedIdentification(auth)else:identification = IpBasedIdentification(server_config.ip_validator, server_config.user_header_name)downloads_folder = file_download_feature.get_result_files_folder()handlers = [(r'/conf', GetServerConf),(r'/scripts', GetScripts),(r'/scripts/([^/]*)', ScriptConfigSocket),(r'/scripts/([^/]*)/([^/]*)/list-files', ScriptParameterListFiles),(r'/executions/start', ScriptExecute),(r'/executions/stop/(.*)', ScriptStop),(r'/executions/kill/(.*)', ScriptKill),(r'/executions/io/(.*)', ScriptStreamSocket),(r'/executions/active', GetActiveExecutionIds),(r'/executions/config/(.*)', GetExecutingScriptConfig),(r'/executions/cleanup/(.*)', CleanupExecutingScript),(r'/executions/status/(.*)', GetExecutionStatus),(r'/history/execution_log/short', GetShortHistoryEntriesHandler),(r'/history/execution_log/long/(.*)', GetLongHistoryEntryHandler),(r'/schedule', AddSchedule),(r'/auth/info', AuthInfoHandler),(r'/result_files/(.*)',DownloadResultFile,{'path': downloads_folder}),(r'/admin/scripts', AdminUpdateScriptEndpoint),(r'/admin/scripts/([^/]+)', AdminScriptEndpoint),(r'/admin/scripts/([^/]*)/code', AdminGetScriptCodeEndpoint),(r"/", ProxiedRedirectHandler, {"url": "/index.html"})]if auth.is_enabled():handlers.append((r'/login', LoginHandler))handlers.append((r'/auth/config', AuthConfigHandler))handlers.append((r'/logout', LogoutHandler))handlers.append((r'/theme/(.*)', ThemeStaticFileHandler, {'path': os.path.join(conf_folder, 'theme')}))handlers.append((r"/(.*)", AuthorizedStaticFileHandler, {"path": "web"}))settings = {'cookie_secret': secret,"login_url": "/login.html",'websocket_ping_interval': 30,'websocket_ping_timeout': 300,'compress_response': True,'xsrf_cookies': server_config.xsrf_protection != XSRF_PROTECTION_DISABLED,}application = tornado.web.Application(handlers, **settings)autoapply_xheaders(application)application.auth = authapplication.server_config = server_configapplication.server_version = server_versionapplication.authorizer = authorizerapplication.downloads_folder = downloads_folderapplication.file_download_feature = file_download_featureapplication.file_upload_feature = file_upload_featureapplication.execution_service = execution_serviceapplication.schedule_service = schedule_serviceapplication.execution_logging_service = execution_logging_serviceapplication.config_service = config_serviceapplication.alerts_service = alerts_serviceapplication.identification = identificationapplication.max_request_size_mb = server_config.max_request_size_mbif os_utils.is_win() and env_utils.is_min_version('3.8'):asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())io_loop = tornado.ioloop.IOLoop.current()global _http_server_http_server = httpserver.HTTPServer(application,ssl_options=ssl_context,max_buffer_size=10 * BYTES_IN_MB)_http_server.listen(server_config.port, address=server_config.address)intercept_stop_when_running_scripts(io_loop, execution_service)http_protocol = 'https' if server_config.ssl else 'http'print('Server is running on: %s://%s:%s' % (http_protocol, server_config.address, server_config.port))if start_server:io_loop.start()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。