async def cookie2user(cookie_str): """ Parse cookie and load user if cookie is valid :param cookie_str: :return: """ if not cookie_str: return None try: L = cookie_str.split('-') if len(L) != 3: return None uid, expires, sha1 = L if int(expires) < time.time(): return None user = await User.find(uid) if user is None: return None s = '%s-%s-%s-%s' % (uid, user.passwd, expires, _COOKIE_KEY) if sha1 != hashlib.sha1(s.encode('utf-8')).hexdigest(): logger.info('invalid sha1') return None user.passwd = '******' return user except Exception as ex: logger.error(traceback.format_exc()) return None
def getvalueordefault(self, key): value = getattr(self, key, None) if value is None: field = self.__mappings__[key] if field.default is not None: value = field.default() if callable(field.default) else field.default logging.debug('using default value for %s: %s' % (key, str(value))) setattr(self, key, value) return value
async def parse_data(request): if request.method == 'POST': if request.content_type.startswith('application/json'): request.__data__ = await request.json() logging.info('request json: %s' % str(request.__data__)) elif request.content_type.startswith( 'application/x-www-form-urlencoded'): request.__data__ = await request.post() logging.info('request form: %s' % str(request.__data__)) return await handler(request)
async def select(sql, args, size=None): log(sql, args) global __pool async with __pool.get() as conn: async with conn.cursor(aiomysql.DictCursor) as cur: await cur.execute(sql.replace('?', '%s'), args or ()) if size: rs = await cur.fetchmany(size) else: rs = await cur.fetchall() logging.info('rows returned: %s' % len(rs)) return rs
async def auth(request): logging.info('check user: %s %s' % (request.method, request.path)) request.__user__ = None cookie_str = request.cookies.get(COOKIE_NAME) if cookie_str: user = await cookie2user(cookie_str) if user: logging.info('set current user: %s' % user.email) request.__user__ = user if request.path.startswith('/manage/') and ( request.__user__ is None or not request.__user__.admin): return web.HTTPFound('/signin') return await handler(request)
async def create_pool(loop, **kw): logging.info('create database connection pool...') global __pool __pool = await aiomysql.create_pool( host=kw.get('host', 'localhost'), port=kw.get('port', 3306), user=kw['user'], password=kw['password'], db=kw['database'], charset=kw.get('charset', 'utf8'), autocommit=kw.get('autocommit', True), maxsize=kw.get('maxsize', 10), minsize=kw.get('minsize', 1), loop=loop )
async def response(request): logging.info('Response handler....') try: r = await handler(request) if isinstance(r, web.StreamResponse): return r if isinstance(r, bytes): resp = web.Response(body=r) resp.content_type = 'application/octet-stream' return resp if isinstance(r, str): if r.startswith('redirect:'): return web.HTTPFound(r[9:]) resp = web.Response(body=r.encode('utf-8')) resp.content_type = 'text/html;charset=utf-8' return resp if isinstance(r, dict): template = r.get('__template__') if template is None: resp = web.Response( body=json.dumps(r, ensure_ascii=False, default=convert).encode('utf-8')) resp.content_type = 'application/json;charset=utf-8' return resp else: r['__user__'] = request.__user__ resp = web.Response( body=app['__templating__'].get_template( template).render(**r).encode('utf-8')) resp.content_type = 'text/html;charset=utf-8' return resp if isinstance(r, int) and 100 <= r < 600: return web.Response(r) if isinstance(r, tuple) and len(r) == 2: t, m = r if isinstance(t, int) and 100 <= t < 600: return web.Response(t, str(m)) except Exception as ex: logging.error(traceback.format_exc()) # traceback.print_exc() resp = web.Response(body=str(r).encode('utf-8')) resp.content_type = 'text/plain;charset=utf-8' return resp
def init_jinja2(app, **kw): logging.info('init jinja2...') 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') logging.info('set jinja2 template path: %s' % path) env = Environment(loader=FileSystemLoader(path), **options) filters = kw.get('filters', None) if filters is not None: for name, f in filters.items(): env.filters[name] = f app['__templating__'] = env
def __new__(mcs, name, bases, attrs): if name == 'Model': return type.__new__(mcs, name, bases, attrs) table_name = attrs.get('__table__', None) or name logging.info('Found model: %s (table: %s)' % (name, table_name)) mappings = dict() fields = [] primarykey = None for k, v in attrs.items(): if isinstance(v, Field): logging.info(' found mapping: %s ==> %s' % (k, v)) mappings[k] = v if v.primary_key: # 找到主键: if primarykey: raise StandardError('Duplicate primary key for field: %s' % k) primarykey = k else: fields.append(k) if not primarykey: raise StandardError('Primary key not found.') for k in mappings.keys(): attrs.pop(k) escaped_fields = list(map(lambda f: '`%s`' % f, fields)) attrs['__mappings__'] = mappings attrs['__table__'] = table_name attrs['__primary_key__'] = primarykey attrs['__fields__'] = fields attrs['__select__'] = 'select `%s`, %s from `%s`' % (primarykey, ', '.join(escaped_fields), table_name) attrs['__insert__'] = 'insert into `%s` (%s, `%s`) values (%s)' % (table_name, ', '.join(escaped_fields), primarykey, create_args_string(len(escaped_fields) + 1)) attrs['__update__'] = 'update `%s` set %s where `%s`=?' % (table_name, ', '.join(map(lambda f: '`%s=?`' %(mappings.get(f).name or f), fields)), primarykey) attrs['__delete__'] = 'delete from `%s` where `%s`=?' % (table_name, primarykey) return type.__new__(mcs, name, bases, attrs)
async def logger(request): logging.info('Request: %s %s' % (request.method, request.path)) return await handler(request)
# await site.start() # # # loop = asyncio.get_event_loop() # loop.run_until_complete(init()) # loop.run_forever() async def init(): # await orm.create_pool(loop=loop, user='******', password='******', db='awesome') await orm.create_pool(loop=loop, **configs['db']) app = web.Application( middlewares=[logger_factory, auth_factory, response_factory]) app_runner = web.AppRunner(app) init_jinja2(app, filters=dict(datetime=datetime_filter)) add_routes(app, 'handlers') add_static(app) await app_runner.setup() site = web.TCPSite(app_runner, '0.0.0.0', 9000) await site.start() try: loop = asyncio.get_event_loop() logging.info('Server started at http://localhost:9000') loop.run_until_complete(init()) print('Launched Completed.') loop.run_forever() except KeyboardInterrupt as e: print('Shut Down....')
async def remove(self): args = [self.getValue(self.__primary_key__)] rows = await execute(self.__delete__, args) if rows != 1: logging.warning('failed to remove by primary key: affected rows: %s' % rows)
async def update(self): args = list(map(self.getvalue, self.__fields__)) args.append(self.getvalue(self.__primary_key__)) rows = await execute(self.__update__, args) if rows != 1: logging.warning('failed to update by primary key: affected rows: %s' % rows)
async def save(self): args = list(map(self.getvalueordefault, self.__fields__)) args.append(self.getvalueordefault(self.__primary_key__)) rows = await execute(self.__insert__, args) if rows != 1: logging.warning('failed to insert record: affected rows: %s' % rows)
def log(sql, args=()): logging.info('SQL: %s' % sql)
def signout(request): referer = request.headers.get('Referer') r = web.HTTPFound(referer or '/') r.set_cookie(COOKIE_NAME, '-deleted-', max_age=0, httponly=True) logger.info('user signed out') return r