async def __call__(self): tm = get_tm() await tm.abort() ws = web.WebSocketResponse() await ws.prepare(self.request) async for msg in ws: if msg.type == aiohttp.WSMsgType.text: try: message = ujson.loads(msg.data) except ValueError: logger.warning( 'Invalid websocket payload, ignored: {}'.format( msg.data)) continue if message['op'] == 'close': await ws.close() elif message['op'].lower() == 'get': txn = await tm.begin() try: await self.handle_ws_request(ws, message) except Exception: logger.error('Exception on ws', exc_info=True) finally: # only currently support GET requests which are *never* # supposed to be commits await tm.abort(txn=txn) elif msg.type == aiohttp.WSMsgType.error: logger.debug( 'ws connection closed with exception {0:s}'.format( ws.exception())) logger.debug('websocket connection closed') return {}
def __run(self, app, settings): if asyncio.iscoroutinefunction(self.run): # Blocking call which returns when finished loop = asyncio.get_event_loop() loop.run_until_complete(self.run(self.arguments, settings, app)) try: loop.run_until_complete(self.cleanup(app)) loop.close() except (asyncio.CancelledError, RuntimeError): logger.warning('Cancelled error on cleanup') else: self.run(self.arguments, settings, app) if self.profiler is not None: if self.arguments.profile_output: self.profiler.dump_stats(self.arguments.profile_output) else: # dump to screen self.profiler.print_stats(-1) if self.line_profiler is not None: self.line_profiler.disable_by_count() if self.arguments.line_profiler_output: self.line_profiler.dump_stats( self.arguments.line_profiler_output) else: self.line_profiler.print_stats()
async def __call__(self): tm = get_tm() await tm.abort() ws = self.request.get_ws() await ws.prepare() async for msg in ws: try: message = msg.json except WebSocketJsonDecodeError: # We only care about json messages logger.warning( "Invalid websocket payload, ignored: {}".format(msg)) continue if message["op"].lower() == "close": break elif message["op"].lower() == "get": txn = await tm.begin() try: await self.handle_ws_request(ws, message) except Exception: logger.error("Exception on ws", exc_info=True) finally: # only currently support GET requests which are *never* # supposed to be commits await tm.abort(txn=txn) logger.debug("websocket connection closed") await ws.close()
def get_settings(configuration): if configuration == 'config.yaml' and not os.path.exists(configuration): # try config.json as well... configuration = 'config.json' if os.path.exists(configuration): with open(configuration, 'r') as config: if configuration.lower().endswith('.json'): settings = json.load(config) else: # should be yaml then... settings = yaml.load(config) settings['__file__'] = configuration else: try: settings = json.loads(configuration) except json.decoder.JSONDecodeError: # try with yaml parser too.. try: settings = yaml.load(configuration) except yaml.parser.ParserError: settings = None if settings is None or settings == configuration: if 'logged' not in MISSING_SETTINGS: logger.warning(f'Could not find the configuration file ' f'{configuration}. Using default settings.') MISSING_SETTINGS['logged'] = True settings = MISSING_SETTINGS.copy() return settings
async def __call__(self): tm = get_tm(self.request) await tm.abort(self.request) ws = web.WebSocketResponse() await ws.prepare(self.request) async for msg in ws: if msg.type == aiohttp.WSMsgType.text: try: message = ujson.loads(msg.data) except ValueError: logger.warning('Invalid websocket payload, ignored: {}'.format( msg.data)) continue if message['op'] == 'close': await ws.close() elif message['op'].lower() == 'get': txn = await tm.begin(request=self.request) try: await self.handle_ws_request(ws, message) except Exception: logger.error('Exception on ws', exc_info=True) finally: # only currently support GET requests which are *never* # supposed to be commits await tm.abort(txn=txn) elif msg.type == aiohttp.WSMsgType.error: logger.debug('ws connection closed with exception {0:s}' .format(ws.exception())) logger.debug('websocket connection closed') return {}
async def wait_for_tasks(self): for task in asyncio.Task.all_tasks(): if task.done(): continue try: logger.info(f'Waiting for {task._coro.__qualname__} to finish') try: await asyncio.wait_for(asyncio.shield(task), 1) except asyncio.TimeoutError: logger.warning(f'Timeout for {task._coro.__qualname__}') except (AttributeError, KeyError): pass
def get_settings(configuration, overrides=None): if configuration == 'config.yaml' and not os.path.exists(configuration): # try config.json as well... configuration = 'config.json' if os.path.exists(configuration): with open(configuration, 'r') as config: if configuration.lower().endswith('.json'): try: settings = json.load(config) except json.decoder.JSONDecodeError: logger.warning('Could not parse json configuration {}'.format( configuration)) raise else: # should be yaml then... settings = yaml.load(config) settings['__file__'] = configuration else: try: settings = json.loads(configuration) except json.decoder.JSONDecodeError: # try with yaml parser too.. try: settings = yaml.load(configuration) # will also parse strings... if isinstance(settings, str): settings = None except yaml.parser.ParserError: settings = None if settings is None or settings == configuration: if 'logged' not in MISSING_SETTINGS: logger.warning(f'No configuration file found. ' f'Using default settings.') MISSING_SETTINGS['logged'] = True settings = MISSING_SETTINGS.copy() for override in overrides or []: if '=' not in override: raise Exception(f'Invalid configuration {override}') name, _, value = override.partition('=') context = settings parts = name.split('.') for part in parts[:-1]: if part not in context: context[part] = {} context = context[part] context[parts[-1]] = value return settings
async def cleanup(self, app): try: await app.shutdown() except Exception: logger.warning("Unhandled error cleanup tasks", exc_info=True) for task in asyncio.Task.all_tasks(): if task.done(): continue if "cleanup" in task._coro.__qualname__: continue try: logger.info(f"Waiting for {task._coro.__qualname__} to finish") try: await asyncio.wait_for(asyncio.shield(task), 1) except asyncio.TimeoutError: logger.warning(f"Timeout for {task._coro.__qualname__}") except (AttributeError, KeyError): pass
def get_settings(configuration): configuration_filename = configuration if configuration == 'config.yaml' and not os.path.exists(configuration): # try config.json as well... configuration_filename = 'config.json' if os.path.exists(configuration_filename): with open(configuration_filename, 'r') as config: if configuration_filename.lower().endswith('.json'): settings = json.load(config) else: # should be yaml then... settings = yaml.load(config) else: logger.warning('Could not find the configuration file {}. Using default settings.'.format( configuration )) settings = MISSING_SETTINGS.copy() return settings
def generate_error_response(self, e, request, error, status=500): # We may need to check the roles of the users to show the real error eid = uuid.uuid4().hex if isinstance(e, asyncio.CancelledError): # pragma: no cover message = _("Cancelled execution of view") + " " + eid logger.warning(message, exc_info=e, eid=eid, request=request) else: message = _("Error on execution of view") + " " + eid logger.error(message, exc_info=e, eid=eid, request=request) data = { "message": message, "reason": error_reasons.UNKNOWN.name, "details": error_reasons.UNKNOWN.details, "eid": eid, } if app_settings.get("debug"): data["traceback"] = traceback.format_exc() return response.HTTPInternalServerError(content=data)
async def cleanup(self, app): try: app.freeze() await app.on_cleanup.send(app) except Exception: logger.warning('Unhandled error cleanup tasks', exc_info=True) for task in asyncio.Task.all_tasks(): if task.done(): continue if 'cleanup' in task._coro.__qualname__: continue try: logger.info(f'Waiting for {task._coro.__qualname__} to finish') try: await asyncio.wait_for(asyncio.shield(task), 1) except asyncio.TimeoutError: logger.warning(f'Timeout for {task._coro.__qualname__}') except (AttributeError, KeyError): pass
def get_settings(configuration, overrides=None): if configuration == "config.yaml" and not os.path.exists(configuration): # try config.json as well... configuration = "config.json" if os.path.exists(configuration): with open(configuration, "r") as config: if configuration.lower().endswith(".json"): try: settings = json.load(config) except json.decoder.JSONDecodeError: logger.warning( "Could not parse json configuration {}".format( configuration)) raise else: # should be yaml then... settings = yaml.load(config, Loader=yaml.FullLoader) settings["__file__"] = configuration else: try: settings = json.loads(configuration) except json.decoder.JSONDecodeError: # try with yaml parser too.. try: settings = yaml.load(configuration, Loader=yaml.FullLoader) # will also parse strings... if isinstance(settings, str): settings = None except yaml.parser.ParserError: settings = None if settings is None or settings == configuration: if "logged" not in MISSING_SETTINGS: logger.warning( f"No configuration file found. Using default settings with DUMMY_FILE db." ) MISSING_SETTINGS["logged"] = True settings = MISSING_SETTINGS.copy() for override in overrides or []: if "=" not in override: raise Exception(f"Invalid configuration {override}") name, _, value = override.partition("=") context = settings parts = name.split(".") for part in parts[:-1]: if part not in context: context[part] = {} context = context[part] context[parts[-1]] = value for env_name in os.environ.keys(): orig_env_name = env_name env_name = env_name.lower() if not env_name.startswith("g_"): continue name = env_name[2:] value = os.environ[orig_env_name] if len(value) > 0 and value[0] in ("{", "["): value = json.loads(value) context = settings parts = name.split("__") for part in parts[:-1]: if part not in context: context[part] = {} context = context[part] context[parts[-1]] = value return settings
def get_settings(configuration, overrides=None): if configuration == 'config.yaml' and not os.path.exists(configuration): # try config.json as well... configuration = 'config.json' if os.path.exists(configuration): with open(configuration, 'r') as config: if configuration.lower().endswith('.json'): try: settings = json.load(config) except json.decoder.JSONDecodeError: logger.warning('Could not parse json configuration {}'.format( configuration)) raise else: # should be yaml then... settings = yaml.load(config, Loader=yaml.FullLoader) settings['__file__'] = configuration else: try: settings = json.loads(configuration) except json.decoder.JSONDecodeError: # try with yaml parser too.. try: settings = yaml.load(configuration, Loader=yaml.FullLoader) # will also parse strings... if isinstance(settings, str): settings = None except yaml.parser.ParserError: settings = None if settings is None or settings == configuration: if 'logged' not in MISSING_SETTINGS: logger.warning(f'No configuration file found. ' f'Using default settings.') MISSING_SETTINGS['logged'] = True settings = MISSING_SETTINGS.copy() for override in overrides or []: if '=' not in override: raise Exception(f'Invalid configuration {override}') name, _, value = override.partition('=') context = settings parts = name.split('.') for part in parts[:-1]: if part not in context: context[part] = {} context = context[part] context[parts[-1]] = value for env_name in os.environ.keys(): if not env_name.startswith('G_'): continue name = env_name[2:].lower() value = os.environ[env_name] if value[0] in ('{', '['): value = json.loads(value) context = settings parts = name.split('__') for part in parts[:-1]: if part not in context: context[part] = {} context = context[part] context[parts[-1]] = value return settings
async def real_resolve(self, request: IRequest) -> MatchInfo: """Main function to resolve a request.""" security = get_adapter(request, IInteraction) if request.method not in app_settings['http_methods']: raise HTTPMethodNotAllowed() method = app_settings['http_methods'][request.method] language = language_negotiation(request) language_object = language(request) try: resource, tail = await self.traverse(request) except ConflictError: # can also happen from connection errors so we bubble this... raise except Exception as _exc: request.resource = request.tail = None request.exc = _exc data = { 'success': False, 'exception_message': str(_exc), 'exception_type': getattr(type(_exc), '__name__', str(type(_exc))), # noqa } if app_settings.get('debug'): data['traceback'] = traceback.format_exc() raise HTTPBadRequest(text=ujson.dumps(data)) request.record('traversed') await notify(ObjectLoadedEvent(resource)) request.resource = resource request.tail = tail if request.resource is None: raise HTTPBadRequest(text='Resource not found') traverse_to = None if tail and len(tail) == 1: view_name = tail[0] elif tail is None or len(tail) == 0: view_name = '' else: view_name = tail[0] traverse_to = tail[1:] await self.apply_authorization(request) request.record('authentication') translator = query_adapter(language_object, ITranslated, args=[resource, request]) if translator is not None: resource = translator.translate() # Add anonymous participation if len(security.participations) == 0: security.add(AnonymousParticipation(request)) # container registry lookup try: view = query_multi_adapter((resource, request), method, name=view_name) except AttributeError: view = None request.found_view = view request.view_name = view_name # Traverse view if its needed if traverse_to is not None and view is not None: if not ITraversableView.providedBy(view): return None else: try: view = await view.publish_traverse(traverse_to) except KeyError: return None # not found, it's okay. except Exception as e: logger.error("Exception on view execution", exc_info=e, request=request) return None permission = get_utility(IPermission, name='guillotina.AccessContent') if not security.check_permission(permission.id, resource): # Check if its a CORS call: if IOPTIONS != method: # Check if the view has permissions explicit if view is None or not view.__allow_access__: logger.warning( "No access content {content} with {auths}".format( content=resource, auths=str([ x.principal.id for x in security.participations ])), request=request) raise HTTPUnauthorized() if view is None and method == IOPTIONS: view = DefaultOPTIONS(resource, request) if view: ViewClass = view.__class__ view_permission = get_view_permission(ViewClass) if not security.check_permission(view_permission, view): logger.warning( "No access for view {content} with {auths}".format( content=resource, auths=str([ x.principal.id for x in security.participations ])), request=request) raise HTTPUnauthorized() request.record('authorization') renderer = content_type_negotiation(request, resource, view) renderer_object = renderer(request) rendered = query_multi_adapter((renderer_object, view, request), IRendered) if rendered is not None: return MatchInfo(resource, request, view, rendered) else: return None