class BaseHandler():

    keyDirs = macros.Macro('KEYDIRS').split(';')  # 注意是关键文件夹名称的列表
    # cached_setup_dir = macros.Macro('CACHEDROOT') +  + 'temp_packages'  # 解压缩的临时文件夹
    configMgr = config.getConfigManager()

    logger = logger.get_logger()

    def __init__(self):
        self.successor = None

    def setSuccessor(self, successor):
        self.successor = successor

    def getSuccessor(self):
        return self.successor

    def handle(self, request):
        raise NotImplementedError('子类必须实现 handle')

    @staticmethod
    def generateExtractDir():
        """
        生成安全的解压目录
        :return:
        """
        return macros.sep.join((macros.Macro('CACHEDROOT'),
                                'InstallExtractDir-' + str(time.time())))
class Appointed2WebApp(Application):

    logger = logger.get_logger('Server')

    def __init__(self, loop, middlewares, topServer):
        Application.__init__(self, middlewares=middlewares, loop=loop)
        self.template = None
        self.topServer = topServer
        self.runtimeInfo = RuntimeInfo()

    def add_statics(self, routerToDirName):
        for router, folder in routerToDirName.items():
            realpath = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                    folder)
            Appointed2WebApp.logger.info('设置静态资源路径: %s' % realpath)
            self.router.add_static(router, realpath)

    def init_template(self, **kw):
        if self.template:
            return
        options = dict(autoescape=kw.get('autoescape', True),
                       block_start_string=kw.get('block_start_string', '{%'),
                       block_end_string=kw.get('block_end_string', '%}'),
                       variable_start_string=kw.get('variable_start_string',
                                                    '{{'),
                       variable_end_string=kw.get('variable_end_string', '}}'),
                       auto_reload=kw.get('auto_reload', True))
        path = kw.get('path', None)
        if path is None:
            path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                'templates')
        env = Environment(loader=FileSystemLoader(path), **options)
        Appointed2WebApp.logger.info(
            '设置 jinja2 模板的路径: %s' %
            os.path.join(os.path.dirname(os.path.abspath(__file__)), path))
        filters = kw.get('filters', None)
        if filters is not None:
            for name, f in filters.items():
                env.filters[name] = f
        self.template = env

    def add_routersBridge(self, packagesMgr):
        for packname, pack in packagesMgr.loadedPackages.items():
            for target_key, routerObj in pack.routers.items():
                self.router.add_route(
                    routerObj.method, routerObj.route,
                    RouterCallBack(routerObj, self, routerObj.system))
                Appointed2WebApp.logger.info('成功添加模块:‘%s’, 路由: %s' %
                                             (packname, str(routerObj)))
                # 初始化路由的基本信息
                self.runtimeInfo.changeEnableStatus(routerObj.flagName,
                                                    routerObj.enable)
from packages import logger
__logger = logger.get_logger("Server")


async def logger_factory(app, handler):
    """
    一个自定义的工厂拦截器,用于显示调用信息
    :param app: 网页服务器实例
    :param handler: 路由处理器
    :return: 返回一个封装的可调用对象
    """
    async def logger_handler(request):
        # logger.get_logger().info('客户端请求: %s %s' % (request.method, request.path))
        __logger.info('客户端请求: %s %s' % (request.method, request.path))
        return await handler(request)  # 转到下一步response_factory

    return logger_handler
Example #4
0
class PackagesManager(object):

    logger = logger.get_logger('Server')

    def __init__(self, packages=[]):
        # self.allRouters = dict()
        self.loadedPackages = dict()
        # 读取制定的包
        for name in packages:
            self.loadedPackages[name] = None  # 还没有加载的情况

    def loadPackages(self):
        """
        加载模块
        :return: 不返回
        """
        try:
            for name in self.loadedPackages.keys():
                if not self.loadedPackages[name]:
                    # 这个模块的名称并没有被加载
                    pack = Package(name)  # 加载模块的信息
                    if not pack.valid:
                        continue
                    # self.allRouters.update(pack.routers)  # 扩展字典
                    self.loadedPackages[name] = pack
        except Exception as e:
            raise e

    def addPackage(self, packageObj):
        if isinstance(packageObj, Package):
            name = packageObj.name
            if not self.loadedPackages.get(name, None):
                self.loadedPackages[name] = packageObj
                PackagesManager.logger.info('手动添加模块:‘%s’ 成功' % name)
            else:
                PackagesManager.logger.info('无法手动添加模块:‘%s’,已经存在相同名称的模块。' %
                                            name)
        else:
            PackagesManager.logger.info('无法手动添加模块:非法的类型。')

    def disablePackage(self, packname):

        packObj = self.loadedPackages.get(packname, None)
        if not packObj:
            raise ValueError('无法找到名为:‘%s’ 的模块' % packname)
        if packObj.main_package:
            raise ValueError('模块‘%s’为系统模块,不允许进行关闭操作!' % packname)
        # 关闭所有的路由
        for router_name, router_obj in packObj.routers.items():
            PackagesManager.logger.warning('正在关闭模块‘%s’ 的路由:%s' %
                                           (packname, router_obj))
            router_obj.enable = False

    def findByName(self, packname):
        """
        查找一个模块对象,按照名称查询。如果不存在返回None
        :param packname:
        :return:
        """
        return self.loadedPackages.get(packname, None)

    def __dict__(self):
        return {'installedPackages': self.loadedPackages}
Example #5
0
class Package(object):
    """
    这个表示Appointed2 定义的子模块对象
    """

    logger = logger.get_logger('Server')

    def __init__(self, packageName, modObj=None, **kwargs):
        """
        模块的信息 __是受保护的内容
        valid:是否有效
        doc:注释信息
        version:模块的信息
        author:作者
        rotuers:可调用对象->{方法,路由,解释,级别,系统}
        commandLines:支持的命令行参数版本
        moduleObject:模块的实例
        main_package:是否是主模块
        :param packageName: 模块的名称
        :return:
        """
        try:
            package_root_modtype = macros.Macro('PACKAGEROOT_IMPORT')
            self.routers = dict()
            self.commandLines = dict()
            self.name = packageName
            self.main_package = False
            if self.name == 'Common':
                self.main_package = True
            if not modObj:
                # 载入packages下的模块
                targetdir = macros.Macro('PACKAGEROOT') + os.sep + packageName
                if not os.path.exists(targetdir) or not os.path.isdir(
                        targetdir):
                    self.valid = False
                    return
                modObj = getattr(
                    __import__(package_root_modtype, globals(), locals(),
                               [packageName]), packageName)  # 导入模块
            if not modObj:
                self.valid = False
                return
            self.valid = True
            self.fullName = '.'.join((package_root_modtype, packageName))
            # 读取doc、version、author以及各个路由器的信息(只在公共接口中__all__)以及路由的命令行格式(如果有)
            if getattr(modObj, '__all__', None):
                # 合法的模块
                for api in getattr(modObj, '__all__', None):
                    fn = getattr(modObj, api)
                    if callable(fn):
                        # 是一个可调用对象
                        method = getattr(fn, '__method__', None)
                        path = getattr(fn, '__route__', None)
                        adminAcquire = getattr(fn, '__adminLevel__', None)
                        if method and path:
                            # 添加路由
                            # self.routers[fn] = {'method': method, 'route': path, 'doc':inspect.getdoc(fn),
                            #                     'level':'api' if path.startswith('/api') else 'user',
                            #                     'system':self.main_package
                            #                     }  # 可调用对象->{方法,路由,解释,级别,系统}
                            # 读取命令行参数
                            if not asyncio.iscoroutinefunction(
                                    fn) and not inspect.isgeneratorfunction(
                                        fn):  # 检查是否是异步函数
                                fn = asyncio.coroutine(fn)
                            # 确定router级别
                            rt_level = 'user'
                            if path.startswith('/api'):
                                rt_level = 'api'
                            elif path.startswith('/ws'):
                                rt_level = 'websocket'
                            rt = Router.Router(
                                method=method,
                                route=path,
                                doc=inspect.getdoc(fn),
                                level=rt_level,
                                system=self.main_package,
                                func=fn,
                                acquireAdmin=adminAcquire)  # 定义成Router 类
                            self.routers[rt.flagName] = rt
            if getattr(modObj, '__cmdLines__', None):
                self.commandLines = modObj.__cmdLines__  # 直接绑定为命令行
            self.version = getattr(modObj, '__version__', '')
            self.author = getattr(modObj, '__author__', '')
            self.doc = getattr(modObj, '__doc__', '')
            self.moduleObject = modObj
            # 构建对象
            Package.logger.info('模块对象‘%s’载入成功' % self.name)
        except Exception as e:
            # 处理错误
            Package.logger.error('初始化模块对象出现问题:%s\n堆栈信息:%s\n' %
                                 (str(e.args), traceback.format_exc()))
            self.valid = False
            raise e

    def _findRouter(self, router_name):
        """
        :param router_name: 指定路由的名称,支持 flagName 和 普通的名称
        查找这个模块中的指定的路由
        :return:
        """
        router_obj = self.routers.get(router_name, None)
        if not router_obj:
            # 可能是其他的名称
            for router_common_name, routerO in self.routers.items():
                if routerO.flagName == router_name:
                    router_obj = routerO
                    break
        if not router_obj:
            Package.logger.error('没有在模块:‘%s’ 找到路由:‘%s’' %
                                 (self.name, router_name))
            return None
        # 已经找到了明确的 路由对象
        return router_obj
        # import objgraph
        # objgraph.show_refs([self.moduleObject.CStarDictIndex], filename='cached\\module.png')
        # del self.moduleObject
        # self.moduleObject = None
        # 删除已经载入的模块
        # modules = [module for module in sys.modules.keys() if module.startswith(self.fullName)]
        # i = 0
        # for module in modules:
        #     print(module, sys.getrefcount(sys.modules[module]))
        #     #
        #     # import objgraph
        #     # objgraph.show_refs([sys.modules[module]], filename='cached\\ref_%d.png' % i)
        #     i = i + 1
        #for module in modules:
        # modules = ['packages.WordBook.dictionaries.langdao','packages.WordBook.dictionaries.oxford','packages.WordBook.dictionaries.youdao','packages.WordBook.OnlineDictionary','packages.WordBook.cpystardict','packages.WordBook.DictionaryModel','packages.WordBook.OfflineDictionaryModel','packages.WordBook.CStarDictIndex']
        #    print(module, sys.getrefcount(sys.modules[module]))  # 引用不能大于3 http://outofmemory.cn/code-snippet/1871/python-xiezai-module
        # tools.unloadAllRefModule(modules)
        # print(sys.modules)

    def setRouter(self, routerName, **kwargs):
        """
        设置路由的相关信息
        :param routerName: 路由的信息
        :param kwargs: 设置的属性以及值
        :return:
        """
        if self.main_package:
            Package.logger.error('不能设置路由:‘%s’ 的属性,因为这个路由属于系统模块:‘%s’。' %
                                 (str(routerName), self.name))
            return False, None
        r = self._findRouter(routerName)
        if not r:
            Package.logger.error('没有找到路由:‘%s’ ' % str(routerName))
            return False, None
        if r.system:
            Package.logger.error('不能设置路由:‘%s’ 的属性,因为这个路由是系统路由。' %
                                 (str(routerName)))
            return False, None
        for key, value in kwargs.items():
            att = getattr(r, key, None)
            if att == None:
                Package.logger.error('不能设置模块:‘%s’ 的路由:‘%s’,属性 ‘%s’' %
                                     (self.name, str(r), key))
                return False, None
            # 判断原来的类型
            typeObj = type(att)
            if typeObj == bool:
                value = tools.ObjToBool(value)
            else:
                pass
            setattr(r, key, value)
            Package.logger.info('设置模块:‘%s’ 的路由:‘%s’,属性 ‘%s’,新值为:‘%s’' %
                                (self.name, str(r), key, value))
        return True, r

    def __dict__(self):
        """
        用于序列化为 字典文件
        :return:
        """
        res = {
            'name': self.name,
            'version': self.version,
            'author': self.author,
            'fullname': self.fullName,
            'doc': self.doc,
            'main_package': self.main_package,
            'routers': self.routers
        }
        return res
Example #6
0
class Appointed2Server(BaseServer):

    logger = logger.get_logger('Server')

    def __init__(self, *args, **kwargs):
        super(Appointed2Server, self).__init__('服务端1')

        # 必须属性
        self.host = kwargs['host']  # 默认绑定的 IP 地址
        self.port = kwargs['port']  # 默认的端口号
        self.loop = kwargs['loop']  # 获取主默认的消息循环
        self.configMgr = kwargs['configMgr']  # 绑定的设置管理器
        self.closeSignal = kwargs['closeSignal']  # 通知监控程序的关闭信号
        self.restartSignal = kwargs['restartSignal']  # 通知监控程序的重启信号
        self.restartEnterManSignal = kwargs['maintenanceSignal']  # 重启进入维护模式的信号
        self.app = Appointed2WebApp.Appointed2WebApp(
            loop=self.loop,
            middlewares=[
                logger_factory.logger_factory, data_factory.data_factory,
                auth_factory.auth_factory, response_factory.response_factory
            ],
            topServer=self)
        # 初始化其他的部件
        self.app.init_template(paths=['templates'])
        self.app.add_statics({
            '/static/': 'static',
            '/templates/': 'templates'
        })
        # 加载模块管理器
        # args 是指定要加载的模块的名称
        self.packagesMgr = Package.PackagesManager(args)
        self.packagesMgr.loadPackages()
        # 服务器主路由
        # modObj = __import__('mainRouters', globals(), locals(), tuple())
        # mainPackage = Package.Package('main', modObj)
        # self.packagesMgr.addPackage(mainPackage)
        # 添加模块的路由
        self.app.add_routersBridge(self.packagesMgr)
        # 创建服务器实例
        handler = self.app.make_handler()
        # 创建服务器
        srv = self.loop.run_until_complete(
            self.loop.create_server(handler, self.host, self.port))
        # 添加资源
        # 设置其他的属性
        self.server = srv
        self.handler = handler
        self.isRunning = False
        self.isMaintenance = False
        # 是否可以进行维护
        if len(self.packagesMgr.loadedPackages) == 1:
            self.isMaintenance = True
        # 初始化数据库
        db_name = kwargs.get('dbname', None)
        if not db_name:
            return  # 不需要数据库连接
        db_username = kwargs['dbusername']
        db_password = kwargs['dbpassword']
        db_addr = kwargs['dbaddress']
        db_port = kwargs['dbport']
        db_dbname = kwargs['dbdbname']
        self.dbPool = self.loop.run_until_complete(
            dbManager.createPool(self.loop, db_username, db_password,
                                 db_dbname, db_addr, db_port))

    def close(self):
        if not self.isRunning:
            return
        # self.loop.run_until_complete(dbManager.destroyPool())
        self.server.close()
        self.loop.run_until_complete(self.server.wait_closed())
        self.loop.run_until_complete(self.app.shutdown())
        self.loop.run_until_complete(self.handler.shutdown(60.0))
        self.loop.run_until_complete(self.app.cleanup())
        self.loop.run_until_complete(dbManager.destroyPool(self.dbPool))
        self.isRunning = False  # 服务关闭
        Appointed2Server.logger.info('Appointed2 服务已经关闭')

    def run(self):
        if self.isRunning:
            return
        self.isRunning = True
        Appointed2Server.logger.info('Appointed2 正在监听:http://%s:%d' %
                                     (self.host, self.port))
        self.loop.run_forever()
        # aiohttp.web.run_app(self.app, host=self.host, port=self.port)

    def user_restart(self, enterMaintenace=False):
        """
        重启服务:直接停止事件循环,并向监控程序发送消息
        :param enterMaintenace:是否进入维护模式?
        :return:
        """
        __logger = Appointed2Server.logger
        if enterMaintenace:
            __logger.info('正在重启 Appointed2 服务并进入维护模式')
        else:
            __logger.info('正在重启 Appointed2 服务')
        mpid = macros.Macro('MONITOR_PID', False)
        sig = self.restartEnterManSignal if enterMaintenace else self.restartSignal
        if mpid:
            if os.name == 'nt':
                from libs import sendMessage as t
                # 获取重启的信号
                __logger.info('向监控进程 ‘%d’ 发送重启信号:‘%s’' % (mpid, sig))
                self.loop.stop()
                t.post(mpid, int(sig))
            else:
                self.loop.stop()
                subprocess.Popen(['kill', '-' + sig,
                                  str(mpid)])  # 默认是 SIGUSR2 信号
                __logger.info('成功向监控进程 ‘%d’ 发送重启信号:‘%s’' % (mpid, sig))

    def user_close(self, sendSignal=True):
        """
        调用对象的关闭服务
        :param sendSignal: 是否向宿主程序发送信号
        :return:
        """
        __logger = Appointed2Server.logger
        __logger.info('正在关闭 Appointed2 服务')
        mpid = macros.Macro('MONITOR_PID', False)
        sig = self.closeSignal
        if mpid:
            if os.name == 'nt':
                from libs import sendMessage as t
                # 获取重启的信号
                __logger.info('向监控进程 ‘%d’ 发送关闭信号:‘%s’' % (mpid, sig))
                self.loop.stop()
                if sendSignal:
                    t.post(mpid, int(sig))
            else:
                self.loop.stop()
                subprocess.Popen(['kill', '-' + sig,
                                  str(mpid)])  # 默认是 SIGUSR2 信号
                __logger.info('成功向监控进程 ‘%d’ 发送关闭信号:‘%s’' % (mpid, sig))
Example #7
0
def run():
    """
    运行服务
    :return: 不返回值
    """
    try:
        global __logger_core
        initEnv.InitEnv(True)

        kws = dict()  # 运行参数
        loop = asyncio.get_event_loop()
        kws['loop'] = loop
        kws['logout'] = True
        # 加载配置设置器
        cfgr = config.getConfigManager()
        kws['configMgr'] = cfgr
        options, noOptArgs = getopt.getopt(
            sys.argv[1:],
            'm:h:p:r:c:e:n',
            (
                'monitorpid=',
                'host=',
                'port=',
                'restartSignal=',
                'closeSignal=',
                'dbname=',
                'dbusername='******'dbpassword='******'dbaddress=',
                'dbport=',
                'dbdbname=',  # 数据库方面
                'maintenanceSignal=',
                'nologout'))
        for name, value in options:
            if name in ('-h', '--host'):
                kws['host'] = value
            elif name in ('-p', '--port'):
                kws['port'] = int(value)
            elif name in ('-n', '--nologout'):
                kws['logout'] = False  # 不显示输出
            elif name in ('-m', '--monitorpid'):
                # 设置监控器PID
                macros.SetMacro('MONITOR_PID', int(value))
            elif name in ('--restartSignal', '-r'):
                kws['restartSignal'] = value
            elif name in ('--closeSignal', '-c'):
                kws['closeSignal'] = value
            elif name in ('--maintenanceSignal', '-e'):
                kws['maintenanceSignal'] = value
            elif name in ('--dbname', ):
                kws['dbname'] = value
            elif name in ('--dbusername', ):
                kws['dbusername'] = value
            elif name in ('--dbpassword', ):
                kws['dbpassword'] = value
            elif name in ('--dbaddress', ):
                kws['dbaddress'] = value
            elif name in ('--dbdbname', ):
                kws['dbdbname'] = value
            elif name in ('--dbport', ):
                kws['dbport'] = int(value)
            else:  # 不允许有不同的参数。可能以后会有可选的配置
                print('%s\n\n未知的参数 ‘%s’' % (__usage, name), file=sys.stderr)
                exit(-1)
        # 是否限定了启动的限定的运行的模块
        if len(noOptArgs) == 0:
            # 读取所有的模块
            packages = cfgr.getInstalledPackages()
            noOptArgs = [
                name for name, infos in packages.items() if infos['enable']
            ]
        macros.SetMacro('HOST', kws['host'])
        macros.SetMacro('PORT', kws['port'])
        macros.SetMacro('ADDRESS', 'http://%s:%d' % (kws['host'], kws['port']))
        signal.signal(signal.SIGTERM, onSignal_KILL)
        # 初始化日志系统
        fp = os.path.sep.join(
            (macros.Macro('LOGROOT'), 'server-%s.txt' % str(time.time())))
        logger.init_logger(fp, kws['logout'])
        __logger_core = logger.get_logger()
    except Exception as e:
        msg = '无法运行Appointed2服务器,因为出现错误%s,消息:%s\n%s' % (str(
            type(e)), str(e.args), traceback.format_exc())
        if __logger_core:
            __logger_core.error(msg)
        else:
            print(msg, file=sys.stderr)
        exit(-1)
    else:
        webApp_obj = None
        try:
            # print(macros.macro)

            webApp_obj = Appointed2Server(*noOptArgs, **kws)
            webApp_obj.run()
        except KeyboardInterrupt:
            pass
        if webApp_obj:
            webApp_obj.close()
__version__ = '0.0.0.1'
__all__ = [
    'EnvironmentPath', 'ObjToBool', 'InstallRequiredModules', 'compareVersion',
    'unloadAllRefModule'
]
__doc__ = 'Appointed2定义的工具函数方便模块对整个程序的运行状态进行获取'
import os
import sys
import subprocess
import sysconfig
from packages import macros, logger
from distutils.version import LooseVersion  # 严格程序的版本
import chardet
import traceback

_logger = logger.get_logger('Server')


def EnvironmentPath(path_type='root', packageType=False):
    """返回服务管理器的路径信息(相对路径)
    path_type : 路径的标志
        root : 服务器的目录
        packages 表示模块的总目录
        <moduleName>:模块的完整名称(从运行的路径开始)
    packageType : 是否是包模式(path_type不为root)
    """
    path = path_type.lower()
    if path == 'root':
        return '.'
    elif path == 'packages':
        return '.' + os.path.sep + 'packages' if not packageType else 'packages'
def signout(request):
    referer = request.headers.get('Referer')
    r = web.HTTPFound(referer or '/manager')  # 设置跳转页面
    r.set_cookie(COOKIE_NAME, '-deleted-', max_age=0, httponly=True)
    logger.get_logger().info("用户退出登陆")
    return r
from packages.Common import Models
import re
import hashlib
from aiohttp import web
import json
import time
from packages import logger, dbManager

COOKIE_NAME = 'appointed2_manager_session'
_COOKIE_KEY = 'welcome'

_RE_EMAIL = re.compile(
    r'^[a-z0-9\.\-\_]+\@[a-z0-9\-\_]+(\.[a-z0-9\-\_]+){1,4}$')
_RE_SHA1 = re.compile(r'^[0-9a-f]{40}$')

_logger = logger.get_logger()


async def create(dbpool, name, password_hash, email, admin_ensureid):
    try:
        if not name or not name.strip():
            raise ValueError('无法创建用户:名称无效')
        if not email or not _RE_EMAIL.match(email):
            raise ValueError('无法创建用户:Email无效')
        if not password_hash or not _RE_SHA1.match(password_hash):
            raise ValueError('无法创建用户:密码格式无效')
        users = await Models.User.findAll(dbpool, 'email=?', [email])
        if len(users) > 0:
            raise ValueError('注册失败', 'Email', '“' + email + '”已经被使用')
        uid = Models.next_id()
        # 检查是否是允许注册为管理员
Example #11
0
    async def __call__(self, request):
        __logger = logger.get_logger()
        # 提取可能的路由
        if not self.router.enable:
            raise ValueError(self.router.method + ' ' + self.router.route +
                             " 不可用")
        # 检查是否需要管理员
        if self.router.acquireAdmin:
            # cookie 的信息
            if not request.__user__ or not request.__user__.admin:
                if request.method == 'POST':
                    if request.__user__:
                        __logger.info(
                            '用户:{user} 尝试 POST {path} 访问失败:需要管理员凭据'.format(
                                user=request.__user__, path=request.path))
                    else:
                        __logger.info('未知用户尝试 POST {path} 访问失败:需要管理员凭据'.format(
                            path=request.path))
                    return (401, '访问未授权,需要管理员凭据')
                # 如果不存在登录的用户、或者还不是管理员账户
                # 跳转到登录界面
                redire = 'redirect:/signin?message=%20路由需要管理员权限%20&redirect=' + request.path_qs
                __logger.info('路由需要管理员的权限,重定向到 %s' % redire)
                return redire
        # 获取函数的参数表
        required_args = inspect.signature(self.router.func).parameters
        # logger.get_logger().info('需要的参数: %s' % required_args)
        # 获取从GET或POST传进来的参数值,如果函数参数表有这参数名就加入

        if request.method == 'POST':
            # for k in dir(request):
            #     print(k + ':' + str(getattr(request, k)))
            if getattr(request, '__data__', None):
                kw = {
                    arg: value
                    for arg, value in request.__data__.items()
                    if arg in required_args
                }  # POST需要进行参数的一些转换,这个转换在data工厂中。数据存储在__data__属性中
            else:
                kw = dict()  # 只有传递了数据才会有__data__
        else:
            # GET参数有可能需要类似于http://xxx.com/blog?id=5&name=ff之类的参数
            qs = request.query_string
            if qs:
                # logger.get_logger().info('GET指令的query参数: %s' % request.query_string)
                kw = {
                    arg: value
                    if isinstance(value, list) and len(value) > 1 else value[0]
                    for arg, value in parse.parse_qs(qs, True).items()
                }  # 保留空格。将查询参数添加到kw已知的参数列表 ref https://raw.githubusercontent.com/icemilk00/Python_L_Webapp/master/www/coroweb.py。可以支持传递数组
            else:
                kw = {
                    arg: value
                    for arg, value in request.match_info.items()
                    if arg in required_args
                }
        # 获取match_info的参数值,例如@get('/blog/{id}')之类的参数值
        kw.update(request.match_info)
        # 如果有request参数的话也加入
        if 'request' in required_args:
            kw['request'] = request
        # 如果有app参数,也添加app参数
        if self.isMain and 'app' in required_args:
            kw['app'] = self.app  # 主要用于main的路由设置
        # 如果需要 websocket 通信
        if self.router.level == 'websocket' and 'wsResponse' in required_args:
            ws = web.WebSocketResponse()
            await ws.prepare(request)
            kw['wsResponse'] = ws  # 使用异步 for 就可以得出消息
        # 检查参数表中有没参数缺失
        for key, arg in required_args.items():
            # request参数不能为可变长参数
            if key == 'request' and arg.kind in (arg.VAR_POSITIONAL,
                                                 arg.VAR_KEYWORD):
                return web.HTTPBadRequest(text='request 参数不能是可变参数')
            # 如果参数类型不是变长列表和变长字典,变长参数是可缺省的
            if arg.kind not in (arg.VAR_POSITIONAL, arg.VAR_KEYWORD):
                # 如果还是没有默认值,而且还没有传值的话就报错
                if arg.default == arg.empty and arg.name not in kw:
                    raise ValueError('缺少的参数: %s' % arg.name)
                    # raise _exceptions.APIError('缺少的参数: %s' % arg.name)

        RouterCallBack.logger.info(
            '使用参数 {paras} 调用路由:{method} {path} 关联的函数'.format(
                paras=kw, method=self.router.method, path=self.router.route))
        try:
            # return await self._func(**kw)
            # 记录请求
            self.app.runtimeInfo.addRequestCount(self.router.flagName)
            return await self.router.func(**kw)
        except Exception as e:
            # 出错记录
            RouterCallBack.logger.error('运行路由处理器期间发生‘%s’类型的错误,错误消息:',
                                        exc_info=True,
                                        stack_info=True)
            raise e
Example #12
0
# coding=utf-8
__author__ = 'Shu Wang <*****@*****.**>'
__version__ = '0.0.0.1'
__all__ = ['']
__doc__ = '维护模式功能 - 维护模式'
import config
from packages import logger, uploader
from packages import setupTool
import time
from queue import Queue
import json

_logger = logger.get_logger('Maintenance')


class RemoteInstallRequest(setupTool.InstallRequest):
    """
    远程用户的请求安装处理
    """
    def __init__(self, packageFile, requestId):
        super(RemoteInstallRequest, self).__init__(packageFile,
                                                   True)  # 制定了安装文件,并且立即显示日志到文件
        self.requestId = requestId

    def __dict__(self):
        if not getattr(self, 'packageStatus', None) or not getattr(
                self, 'packageInfoObj', None):
            return {'name': '未知', 'version': '未知', 'author': '未知'}
        else:
            return self.packageInfoObj.__dict__()