async def _local_request(self, method, uri, cookies=None, *args, **kwargs): import aiohttp if uri.startswith(('http:', 'https:', 'ftp:', 'ftps://' '//')): url = uri else: url = 'http://{host}:{port}{uri}'.format( host=HOST, port=PORT, uri=uri) log.info(url) conn = aiohttp.TCPConnector(verify_ssl=False) async with aiohttp.ClientSession( cookies=cookies, connector=conn) as session: async with getattr( session, method.lower())(url, *args, **kwargs) as response: try: response.text = await response.text() except UnicodeDecodeError as e: response.text = None try: response.json = await response.json() except (JSONDecodeError, UnicodeDecodeError, aiohttp.ClientResponseError): response.json = None response.body = await response.read() return response
def run(self, host=None, port=None, debug=False, ssl=None, sock=None, workers=1, protocol=None, backlog=100, stop_event=None, register_sys_signals=True, log_config=None): """Run the HTTP Server and listen until keyboard interrupt or term signal. On termination, drain connections before closing. :param host: Address to host on :param port: Port to host on :param debug: Enables debug output (slows server) :param ssl: SSLContext, or location of certificate and key for SSL encryption of worker(s) :param sock: Socket for the server to accept connections from :param workers: Number of processes received before it is respected :param backlog: :param stop_event: :param register_sys_signals: :param protocol: Subclass of asyncio protocol class :return: Nothing """ if sock is None: host, port = host or "127.0.0.1", port or 8000 if log_config: self.log_config = log_config logging.config.dictConfig(log_config) if protocol is None: protocol = (WebSocketProtocol if self.websocket_enabled else HttpProtocol) if stop_event is not None: if debug: warnings.simplefilter('default') warnings.warn("stop_event will be removed from future versions.", DeprecationWarning) server_settings = self._helper( host=host, port=port, debug=debug, ssl=ssl, sock=sock, workers=workers, protocol=protocol, backlog=backlog, register_sys_signals=register_sys_signals, has_log=self.log_config is not None) try: self.is_running = True if workers == 1: serve(**server_settings) else: serve_multiple(server_settings, workers) except: log.exception( 'Experienced exception while trying to serve') raise finally: self.is_running = False log.info("Server Stopped")
def before_stop(app, loop): log.info("TRIED EVERYTHING")
def log_reload(self, filename): """Log reload.""" filename = os.path.abspath(filename) log.info(' * Detected change in %r, reloading' % filename)
def serve(host, port, request_handler, error_handler, before_start=None, after_start=None, before_stop=None, after_stop=None, debug=False, request_timeout=60, ssl=None, sock=None, request_max_size=None, reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100, register_sys_signals=True, run_async=False, connections=None, signal=Signal()): """Start asynchronous HTTP Server on an individual process. :param host: Address to host on :param port: Port to host on :param request_handler: Sanic request handler with middleware :param error_handler: Sanic error handler with middleware :param before_start: function to be executed before the server starts listening. Takes arguments `app` instance and `loop` :param after_start: function to be executed after the server starts listening. Takes arguments `app` instance and `loop` :param before_stop: function to be executed when a stop signal is received before it is respected. Takes arguments `app` instance and `loop` :param after_stop: function to be executed when a stop signal is received after it is respected. Takes arguments `app` instance and `loop` :param debug: enables debug output (slows server) :param request_timeout: time in seconds :param ssl: SSLContext :param sock: Socket for the server to accept connections from :param request_max_size: size in bytes, `None` for no limit :param reuse_port: `True` for multiple workers :param loop: asyncio compatible event loop :param protocol: subclass of asyncio protocol class :return: Nothing """ if not run_async: loop = async_loop.new_event_loop() asyncio.set_event_loop(loop) if debug: loop.set_debug(debug) trigger_events(before_start, loop) connections = connections if connections is not None else set() server = partial( protocol, loop=loop, connections=connections, signal=signal, request_handler=request_handler, error_handler=error_handler, request_timeout=request_timeout, request_max_size=request_max_size, ) server_coroutine = loop.create_server(server, host, port, ssl=ssl, reuse_port=reuse_port, sock=sock, backlog=backlog) # Instead of pulling time at the end of every request, # pull it once per minute loop.call_soon(partial(update_current_time, loop)) if run_async: return server_coroutine try: http_server = loop.run_until_complete(server_coroutine) except: log.exception("Unable to start server") return trigger_events(after_start, loop) # Register signals for graceful termination if register_sys_signals: for _signal in (SIGINT, SIGTERM): try: loop.add_signal_handler(_signal, loop.stop) except NotImplementedError: log.warn('Sanic tried to use loop.add_signal_handler but it is' ' not implemented on this platform.') pid = os.getpid() try: log.info('Starting worker [{}]'.format(pid)) loop.run_forever() finally: log.info("Stopping worker [{}]".format(pid)) # Run the on_stop function if provided trigger_events(before_stop, loop) # Wait for event loop to finish and all connections to drain http_server.close() loop.run_until_complete(http_server.wait_closed()) # Complete all tasks on the loop signal.stopped = True for connection in connections: connection.close_if_idle() while connections: loop.run_until_complete(asyncio.sleep(0.1)) trigger_events(after_stop, loop) loop.close()
async def test(request): log.info("Received GET /") return json(await expensive_call())
def run(self, host="127.0.0.1", port=8000, debug=False, before_start=None, after_start=None, before_stop=None, after_stop=None, ssl=None, sock=None, workers=1, loop=None, protocol=None, backlog=100, stop_event=None, register_sys_signals=True): """Run the HTTP Server and listen until keyboard interrupt or term signal. On termination, drain connections before closing. :param host: Address to host on :param port: Port to host on :param debug: Enables debug output (slows server) :param before_start: Functions to be executed before the server starts accepting connections :param after_start: Functions to be executed after the server starts accepting connections :param before_stop: Functions to be executed when a stop signal is received before it is respected :param after_stop: Functions to be executed when all requests are complete :param ssl: SSLContext for SSL encryption of worker(s) :param sock: Socket for the server to accept connections from :param workers: Number of processes received before it is respected :param loop: :param backlog: :param stop_event: :param register_sys_signals: :param protocol: Subclass of asyncio protocol class :return: Nothing """ if protocol is None: protocol = (WebSocketProtocol if self.websocket_enabled else HttpProtocol) server_settings = self._helper( host=host, port=port, debug=debug, before_start=before_start, after_start=after_start, before_stop=before_stop, after_stop=after_stop, ssl=ssl, sock=sock, workers=workers, loop=loop, protocol=protocol, backlog=backlog, stop_event=stop_event, register_sys_signals=register_sys_signals) try: self.is_running = True if workers == 1: serve(**server_settings) else: serve_multiple(server_settings, workers, stop_event) except: log.exception('Experienced exception while trying to serve') finally: self.is_running = False log.info("Server Stopped")
def run(self, host=None, port=None, debug=False, ssl=None, sock=None, workers=1, protocol=None, backlog=100, stop_event=None, register_sys_signals=True, log_config=None): """Run the HTTP Server and listen until keyboard interrupt or term signal. On termination, drain connections before closing. :param host: Address to host on :param port: Port to host on :param debug: Enables debug output (slows server) :param ssl: SSLContext, or location of certificate and key for SSL encryption of worker(s) :param sock: Socket for the server to accept connections from :param workers: Number of processes received before it is respected :param backlog: :param stop_event: :param register_sys_signals: :param protocol: Subclass of asyncio protocol class :return: Nothing """ if sock is None: host, port = host or "127.0.0.1", port or 8000 if log_config: self.log_config = log_config logging.config.dictConfig(log_config) if protocol is None: protocol = (WebSocketProtocol if self.websocket_enabled else HttpProtocol) if stop_event is not None: if debug: warnings.simplefilter('default') warnings.warn("stop_event will be removed from future versions.", DeprecationWarning) server_settings = self._helper( host=host, port=port, debug=debug, ssl=ssl, sock=sock, workers=workers, protocol=protocol, backlog=backlog, register_sys_signals=register_sys_signals, has_log=self.log_config is not None) try: self.is_running = True if workers == 1: serve(**server_settings) else: serve_multiple(server_settings, workers) except: log.exception('Experienced exception while trying to serve') raise finally: self.is_running = False log.info("Server Stopped")
def before_stop(loop): log.info("TRIED EVERYTHING")
def serve(host, port, request_handler, error_handler, before_start=None, after_start=None, before_stop=None, after_stop=None, debug=False, request_timeout=60, ssl=None, sock=None, request_max_size=None, reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100, register_sys_signals=True, run_async=False, connections=None, signal=Signal(), request_class=None, has_log=True, keep_alive=True, is_request_stream=False, router=None, websocket_max_size=None, websocket_max_queue=None, state=None, graceful_shutdown_timeout=15.0): """Start asynchronous HTTP Server on an individual process. :param host: Address to host on :param port: Port to host on :param request_handler: Sanic request handler with middleware :param error_handler: Sanic error handler with middleware :param before_start: function to be executed before the server starts listening. Takes arguments `app` instance and `loop` :param after_start: function to be executed after the server starts listening. Takes arguments `app` instance and `loop` :param before_stop: function to be executed when a stop signal is received before it is respected. Takes arguments `app` instance and `loop` :param after_stop: function to be executed when a stop signal is received after it is respected. Takes arguments `app` instance and `loop` :param debug: enables debug output (slows server) :param request_timeout: time in seconds :param ssl: SSLContext :param sock: Socket for the server to accept connections from :param request_max_size: size in bytes, `None` for no limit :param reuse_port: `True` for multiple workers :param loop: asyncio compatible event loop :param protocol: subclass of asyncio protocol class :param request_class: Request class to use :param has_log: disable/enable access log and error log :param is_request_stream: disable/enable Request.stream :param router: Router object :return: Nothing """ if not run_async: loop = async_loop.new_event_loop() asyncio.set_event_loop(loop) if debug: loop.set_debug(debug) connections = connections if connections is not None else set() server = partial( protocol, loop=loop, connections=connections, signal=signal, request_handler=request_handler, error_handler=error_handler, request_timeout=request_timeout, request_max_size=request_max_size, request_class=request_class, has_log=has_log, keep_alive=keep_alive, is_request_stream=is_request_stream, router=router, websocket_max_size=websocket_max_size, websocket_max_queue=websocket_max_queue, state=state, debug=debug, ) server_coroutine = loop.create_server( server, host, port, ssl=ssl, reuse_port=reuse_port, sock=sock, backlog=backlog ) # Instead of pulling time at the end of every request, # pull it once per minute loop.call_soon(partial(update_current_time, loop)) if run_async: return server_coroutine trigger_events(before_start, loop) try: http_server = loop.run_until_complete(server_coroutine) except: log.exception("Unable to start server") return trigger_events(after_start, loop) # Register signals for graceful termination if register_sys_signals: for _signal in (SIGINT, SIGTERM): try: loop.add_signal_handler(_signal, loop.stop) except NotImplementedError: log.warn('Sanic tried to use loop.add_signal_handler but it is' ' not implemented on this platform.') pid = os.getpid() try: log.info('Starting worker [{}]'.format(pid)) loop.run_forever() finally: log.info("Stopping worker [{}]".format(pid)) # Run the on_stop function if provided trigger_events(before_stop, loop) # Wait for event loop to finish and all connections to drain http_server.close() loop.run_until_complete(http_server.wait_closed()) # Complete all tasks on the loop signal.stopped = True for connection in connections: connection.close_if_idle() # Gracefully shutdown timeout. # We should provide graceful_shutdown_timeout, # instead of letting connection hangs forever. # Let's roughly calcucate time. start_shutdown = 0 while connections and (start_shutdown < graceful_shutdown_timeout): loop.run_until_complete(asyncio.sleep(0.1)) start_shutdown = start_shutdown + 0.1 # Force close non-idle connection after waiting for # graceful_shutdown_timeout coros = [] for conn in connections: if hasattr(conn, "websocket") and conn.websocket: coros.append(conn.websocket.close_connection(force=True)) else: conn.close() _shutdown = asyncio.gather(*coros, loop=loop) loop.run_until_complete(_shutdown) trigger_events(after_stop, loop) loop.close()
async def close_mysql(_app, loop): _app.mysql.close() log.info('closing mysql connection for [pid:{}]'.format( os.getpid())) await _app.mysql.wait_closed()
async def ping(request): if settings.DEBUG: log.info('/ping') return response.json({'status': 'ok'})
async def sub_close(app, loop): log.info("mongo connection {numbr}".format(numbr=len(self.GridFSs))) for bucket_name,bucket in self.GridFSs.items(): bucket.client.close log.info("{bucket_name} connection closed".format(bucket_name=bucket_name))
async def expensive_call(): log.info("Expensive has been called") await asyncio.sleep(3) return {"test": True}
def serve(host, port, request_handler, error_handler, debug=False, request_timeout=60, sock=None, request_max_size=None, reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100): """ 在一个独立进程中启动异步 HTTP 服务器. :param host: 服务器地址 :param port: 服务器端口 :param request_handler: 请求处理器 :param error_handler: 异常处理器 :param debug: 开启 debug 输出 :param request_timeout: 以秒为单位,请求超时时间 :param sock: 接受连接的套接字 :param request_max_size: 大小以字节为单位,`None`代表无限制 :param reuse_port: `True` for multiple workers :param loop: 异步事件循环 :param protocol: 异步协议类的子类 """ # 创建事件循环 loop = loop or async_loop.new_event_loop() asyncio.set_event_loop(loop) # 开启 debug if debug: loop.set_debug(debug) connections = set() signal = Signal() # 配置 server 参数 server = partial( protocol, loop=loop, connections=connections, signal=signal, request_handler=request_handler, error_handler=error_handler, request_timeout=request_timeout, request_max_size=request_max_size, ) # 创建 server 协程 server_coroutine = loop.create_server( server, host, port, reuse_port=reuse_port, sock=sock, backlog=backlog ) # 每分钟都 pull time,而不是在每个请求结束后 loop.call_soon(partial(update_current_time, loop)) try: http_server = loop.run_until_complete(server_coroutine) # 启动协程 except Exception: log.exception("Unable to start server") return # Register signals for graceful termination for _signal in (SIGINT, SIGTERM): loop.add_signal_handler(_signal, loop.stop) # 启动服务器 try: loop.run_forever() finally: log.info("Stop requested, draining connections...") # 事件循环解说后释放所有连接 http_server.close() loop.run_until_complete(http_server.wait_closed()) # 再循环中完成所有 tasks signal.stopped = True for connection in connections: connection.close_if_idle() while connections: loop.run_until_complete(asyncio.sleep(0.1)) loop.close()
async def reuse(request): log.info("Received GET /reuse") return json(await reuse_data())
def after_start(loop): log.info("OH OH OH OH OHHHHHHHH")
def before_start(loop): log.info("OH OH OH OH OHHHHHHHH")
def _helper(self, host="127.0.0.1", port=8000, debug=False, before_start=None, after_start=None, before_stop=None, after_stop=None, ssl=None, sock=None, workers=1, loop=None, protocol=HttpProtocol, backlog=100, stop_event=None, register_sys_signals=True, run_async=False, has_log=True): """Helper function used by `run` and `create_server`.""" if isinstance(ssl, dict): # try common aliaseses cert = ssl.get('cert') or ssl.get('certificate') key = ssl.get('key') or ssl.get('keyfile') if cert is None or key is None: raise ValueError("SSLContext or certificate and key required.") context = create_default_context(purpose=Purpose.CLIENT_AUTH) context.load_cert_chain(cert, keyfile=key) ssl = context if stop_event is not None: if debug: warnings.simplefilter('default') warnings.warn("stop_event will be removed from future versions.", DeprecationWarning) if loop is not None: if debug: warnings.simplefilter('default') warnings.warn("Passing a loop will be deprecated in version" " 0.4.0 https://github.com/channelcat/sanic/" "pull/335 has more information.", DeprecationWarning) # Deprecate this if any(arg is not None for arg in (after_stop, after_start, before_start, before_stop)): if debug: warnings.simplefilter('default') warnings.warn("Passing a before_start, before_stop, after_start or" "after_stop callback will be deprecated in next " "major version after 0.4.0", DeprecationWarning) self.error_handler.debug = debug self.debug = debug server_settings = { 'protocol': protocol, 'request_class': self.request_class, 'host': host, 'port': port, 'sock': sock, 'ssl': ssl, 'signal': Signal(), 'debug': debug, 'request_handler': self.handle_request, 'error_handler': self.error_handler, 'request_timeout': self.config.REQUEST_TIMEOUT, 'request_max_size': self.config.REQUEST_MAX_SIZE, 'keep_alive': self.config.KEEP_ALIVE, 'loop': loop, 'register_sys_signals': register_sys_signals, 'backlog': backlog, 'has_log': has_log } # -------------------------------------------- # # Register start/stop events # -------------------------------------------- # for event_name, settings_name, reverse, args in ( ("before_server_start", "before_start", False, before_start), ("after_server_start", "after_start", False, after_start), ("before_server_stop", "before_stop", True, before_stop), ("after_server_stop", "after_stop", True, after_stop), ): listeners = self.listeners[event_name].copy() if args: if callable(args): listeners.append(args) else: listeners.extend(args) if reverse: listeners.reverse() # Prepend sanic to the arguments when listeners are triggered listeners = [partial(listener, self) for listener in listeners] server_settings[settings_name] = listeners if debug: log.setLevel(logging.DEBUG) if self.config.LOGO is not None: log.debug(self.config.LOGO) if run_async: server_settings['run_async'] = True # Serve if host and port: proto = "http" if ssl is not None: proto = "https" log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port)) return server_settings
def before_stop(app, loop): log.info("SERVER STOPPING")
def sig_handler(signal, frame): log.info("Received signal {}. Shutting down.".format( Signals(signal).name)) for process in processes: os.kill(process.pid, SIGINT)
def after_stop(app, loop): log.info("TRIED EVERYTHING")
def _helper(self, host="127.0.0.1", port=8000, debug=False, before_start=None, after_start=None, before_stop=None, after_stop=None, ssl=None, sock=None, workers=1, loop=None, protocol=HttpProtocol, backlog=100, stop_event=None, register_sys_signals=True, run_async=False): """Helper function used by `run` and `create_server`.""" if loop is not None: if debug: warnings.simplefilter('default') warnings.warn( "Passing a loop will be deprecated in version" " 0.4.0 https://github.com/channelcat/sanic/" "pull/335 has more information.", DeprecationWarning) # Deprecate this if any(arg is not None for arg in (after_stop, after_start, before_start, before_stop)): if debug: warnings.simplefilter('default') warnings.warn( "Passing a before_start, before_stop, after_start or" "after_stop callback will be deprecated in next " "major version after 0.4.0", DeprecationWarning) self.error_handler.debug = debug self.debug = debug server_settings = { 'protocol': protocol, 'host': host, 'port': port, 'sock': sock, 'ssl': ssl, 'debug': debug, 'request_handler': self.handle_request, 'error_handler': self.error_handler, 'request_timeout': self.config.REQUEST_TIMEOUT, 'request_max_size': self.config.REQUEST_MAX_SIZE, 'loop': loop, 'register_sys_signals': register_sys_signals, 'backlog': backlog } # -------------------------------------------- # # Register start/stop events # -------------------------------------------- # for event_name, settings_name, reverse, args in ( ("before_server_start", "before_start", False, before_start), ("after_server_start", "after_start", False, after_start), ("before_server_stop", "before_stop", True, before_stop), ("after_server_stop", "after_stop", True, after_stop), ): listeners = self.listeners[event_name].copy() if args: if callable(args): listeners.append(args) else: listeners.extend(args) if reverse: listeners.reverse() # Prepend sanic to the arguments when listeners are triggered listeners = [partial(listener, self) for listener in listeners] server_settings[settings_name] = listeners if debug: log.setLevel(logging.DEBUG) if self.config.LOGO is not None: log.debug(self.config.LOGO) if run_async: server_settings['run_async'] = True # Serve proto = "http" if ssl is not None: proto = "https" log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port)) return server_settings
def before_start(app, loop): log.info("SERVER STARTING")
def _helper(self, host=None, port=None, debug=False, ssl=None, sock=None, workers=1, loop=None, protocol=HttpProtocol, backlog=100, stop_event=None, register_sys_signals=True, run_async=False, has_log=True): """Helper function used by `run` and `create_server`.""" if isinstance(ssl, dict): # try common aliaseses cert = ssl.get('cert') or ssl.get('certificate') key = ssl.get('key') or ssl.get('keyfile') if cert is None or key is None: raise ValueError("SSLContext or certificate and key required.") context = create_default_context(purpose=Purpose.CLIENT_AUTH) context.load_cert_chain(cert, keyfile=key) ssl = context if stop_event is not None: if debug: warnings.simplefilter('default') warnings.warn("stop_event will be removed from future versions.", DeprecationWarning) self.error_handler.debug = debug self.debug = debug server_settings = { 'protocol': protocol, 'request_class': self.request_class, 'is_request_stream': self.is_request_stream, 'router': self.router, 'host': host, 'port': port, 'sock': sock, 'ssl': ssl, 'signal': Signal(), 'debug': debug, 'request_handler': self.handle_request, 'error_handler': self.error_handler, 'request_timeout': self.config.REQUEST_TIMEOUT, 'request_max_size': self.config.REQUEST_MAX_SIZE, 'keep_alive': self.config.KEEP_ALIVE, 'loop': loop, 'register_sys_signals': register_sys_signals, 'backlog': backlog, 'has_log': has_log, 'websocket_max_size': self.config.WEBSOCKET_MAX_SIZE, 'websocket_max_queue': self.config.WEBSOCKET_MAX_QUEUE, 'graceful_shutdown_timeout': self.config.GRACEFUL_SHUTDOWN_TIMEOUT } # -------------------------------------------- # # Register start/stop events # -------------------------------------------- # for event_name, settings_name, reverse in ( ("before_server_start", "before_start", False), ("after_server_start", "after_start", False), ("before_server_stop", "before_stop", True), ("after_server_stop", "after_stop", True), ): listeners = self.listeners[event_name].copy() if reverse: listeners.reverse() # Prepend sanic to the arguments when listeners are triggered listeners = [partial(listener, self) for listener in listeners] server_settings[settings_name] = listeners if debug: log.setLevel(logging.DEBUG) if self.config.LOGO is not None: log.debug(self.config.LOGO) if run_async: server_settings['run_async'] = True # Serve if host and port: proto = "http" if ssl is not None: proto = "https" log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port)) return server_settings
def sig_handler(signal, frame): log.info("Received signal {}. Shutting down.".format( Signals(signal).name))
import settings from controller import bp_v1, bp_v2 __author__ = 'lpe234' app = Sanic(name='SanicDemo') # load config by hostname, and check config. host_name = socket.gethostname().capitalize().replace('.', '_').replace('-', '') app.config.from_object( getattr(settings, '{}Config'.format(host_name), settings.Config)) if app.config.get('CONFIG_NAME'): info_msg = 'load config from: {}'.format(app.config.get('CONFIG_NAME')) log.info(info_msg) else: err_msg = 'Config Wrong, Please Check With host_name: {}'.format(host_name) exit(err_msg) # register blueprints on the app app.blueprint(bp_v1, url_prefix='/v1') app.blueprint(bp_v2, url_prefix='/v2') @app.get('/') async def test(request): return json({'hello': 'world'}) if __name__ == '__main__':
def after_start(app, loop): log.info("OH OH OH OH OHHHHHHHH")
def default_close_connection(app, loop): if hasattr(app, 'motor_client'): log.info('closing motor connection') app.motor_client.close()