Esempio n. 1
0
def run():
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

    parser = argparse.ArgumentParser(description="Sertifikatsok API")
    parser.add_argument("--host")
    parser.add_argument("--path")
    parser.add_argument("--port")
    parser.add_argument("--log-level")
    parser.add_argument("--log-files")
    parser.add_argument("--dev", action="store_true")

    args = parser.parse_args()

    if args.log_level:
        log_level = getattr(logging, args.log_level)
    elif args.dev:
        log_level = logging.DEBUG
    else:
        log_level = logging.INFO
    configure_logging(log_level, args.log_files)

    app = web.Application(
        middlewares=[error_middleware, correlation_middleware])
    app.router.add_get("/api", api_endpoint)
    app.on_startup.append(init_app)
    app["dev"] = False

    if args.dev:
        from aiohttp_swagger import setup_swagger

        setup_swagger(app)

        app["dev"] = True

    web.run_app(app, port=args.port, host=args.host, path=args.path)
Esempio n. 2
0
async def init_app() -> web.Application:
    app = await create_app()

    # read app config
    config = load_config(settings.BASE_DIR, settings.CONFIG_TRAFARET)
    app['config'] = config

    # setup logging settings
    logging_settings = import_from_string(app['config']['logging'])
    logging.config.dictConfig(logging_settings)

    # create db
    db = await create_db_engine(**config['database'])
    app['db'] = db

    # create HTTP client
    http_client = ClientSession()
    app['http_client'] = http_client

    # init sub apps
    await init_subapps(app)

    # init swagger if it need
    if app['config']['swagger']:
        logger.debug(f'Init swagger')
        setup_swagger(app)

    app.on_cleanup.append(deinit_app)

    return app
Esempio n. 3
0
    async def server_init(self):
        self.app = web.Application()
        self.app.on_startup.append(self.on_startup)
        self.app.on_shutdown.append(self.on_shutdown)
        self.app.on_cleanup.append(self.on_cleanup)
        hsm_pool = HsmPool()
        self.app['hsm_pool'] = hsm_pool

        cors = aiohttp_cors.setup(self.app,
                                  defaults={
                                      "*":
                                      aiohttp_cors.ResourceOptions(
                                          allow_credentials=True,
                                          expose_headers="*",
                                          allow_headers="*",
                                      )
                                  })

        sample_service = SampleService()
        sample_service.app['hsm_pool'] = self.app['hsm_pool']
        self.app.add_subapp("/sample/", sample_service.app)

        setup_swagger(self.app)

        for route in self.app.router.routes():
            cors.add(route)

        self.runner = web.AppRunner(self.app)
        await self.runner.setup()
        site = web.TCPSite(self.runner, self.addr, self.port)
        await site.start()
        print(f"======== Running on http://{site._host}:{site._port} ========")
Esempio n. 4
0
def app_config(app):
    """Add app configs."""
    app.on_startup.append(startup)
    app.on_cleanup.append(cleanup)
    map_routes(app)
    setup_swagger(app, swagger_from_file="app/config/swagger.yaml")
    return app
Esempio n. 5
0
    def run(config_path, translation_engine_adapter):
        # Load config
        os.chdir(
            os.path.dirname(os.path.abspath(sys.modules['__main__'].__file__)))
        with open(config_path) as f:
            config = yaml.load(f, Loader=yaml.FullLoader)

        # Create server
        server = Server(config, translation_engine_adapter)

        # Add routes
        server.add_routes([
            web.post('/translate', server.translate),
            web.get('/ui-init', server.ui_init),
            web.static('/ui', "ui"),
            web.get('/', server.index),
            web.get('/test', server.test)
        ])

        # Background
        server.on_startup.append(server.start_background)
        server.on_cleanup.append(server.stop_background)

        setup_swagger(server)

        # Run
        web.run_app(server,
                    host=config["gatewayServer"]["host"],
                    port=config["gatewayServer"]["port"])
Esempio n. 6
0
    async def setup_routes_and_swagger(self):
        """
        Setup NvidaSettings service to get available items
        and then create corresponding routes and swagger documentation
        """

        items = await self.app['nvidia_settings'].return_available_items()
        self.generate_swagger_dict(items)

        swagger_url = self.route_join(self.config.context_path, '/swagger')

        aiohttp_swagger.setup_swagger(
            self.app,
            swagger_info=self.d_swagger,
            api_base_url=self.config.context_path,
            swagger_url=swagger_url,
        )
        self.app.router.add_route('GET', '/', lambda x: aiohttp.web.HTTPFound(swagger_url))

        for url, params in self.d_swagger['paths'].items():
            if 'get' in params:
                resp_schema = params['get']['responses'][200]['schema']['properties']
                self.logger.info('GET %s: returns %s', url, resp_schema)
                self.app.router.add_route('GET', url, self.handler)
            if 'post' in params:
                body_schema = params['post']['parameters'][0]['schema']['properties']
                resp_schema = params['get']['responses'][200]['schema']['properties']
                self.logger.info('POST %s: with body: %s returns %s', url, body_schema, resp_schema)
                self.app.router.add_route('POST', url, self.handler)
Esempio n. 7
0
async def init(loop):
    app = web.Application(loop=loop)

    # Configure default CORS settings.
    cors = aiohttp_cors.setup(app,
                              defaults={
                                  "*":
                                  aiohttp_cors.ResourceOptions(
                                      allow_credentials=True,
                                      expose_headers="*",
                                      allow_headers="*",
                                      allow_methods="*",
                                  )
                              })

    # Routes
    cors.add(app.router.add_route('*', '/todos/', IndexView), webview=True)
    cors.add(app.router.add_route('*', '/todos/{uuid}', TodoView, name='todo'),
             webview=True)

    # Config
    setup_swagger(app,
                  swagger_url="/api/v1/doc",
                  swagger_from_file="swagger.yaml")
    logger.info("Starting server at %s:%s", IP, PORT)
    srv = await loop.create_server(app.make_handler(), IP, PORT)
    return srv
Esempio n. 8
0
 async def start(self):
     setup_swagger(self.__app, swagger_url='/v1/docs')
     runner = web.AppRunner(self.__app)
     await runner.setup()
     service = web.TCPSite(runner, self.__host, self.__port)
     await service.start()
     self.logger.info('Service is started at %s:%s', self.__host, self.__port)
Esempio n. 9
0
async def create_app():
    """
    Initialize the application server
    """
    base_path = '/api/v1'
    # Init application
    app = ImageApplication()

    storage_path = os.path.join(os.path.dirname(__file__), 'storage')
    img_path = os.path.join(storage_path, 'img')
    thumbnail_path = os.path.join(storage_path, 'thumbnail')
    if not os.path.exists(storage_path):
        os.makedirs(storage_path)
        # create img dirs inside
        os.makedirs(img_path)
        os.makedirs(thumbnail_path)

    app['img_dir'] = img_path
    app['thumbnail_dir'] = thumbnail_path
    app['db'] = os.path.join(storage_path, 'image_db.sqlite3')
    app['tmp_dir'] = pathlib.Path(tempfile.mkdtemp())

    # include swagger file under /api/doc endpoint
    setup_swagger(
        app, swagger_url=f'{base_path}/doc', swagger_from_file=abs_path('specs/svc_img_v1.yml'))

    # Configure v1 routes
    subapp_v1 = await app_v1.init_subapp()
    app.add_subapp(base_path, subapp_v1)

    app.on_startup.append(on_startup)
    app.on_shutdown.append(on_shutdown)
    logger.info('Application started')
    return app
Esempio n. 10
0
    async def _start(self, address, port):
        """
        Start cirrina server.

        This method starts the asyncio loop server which uses
        the aiohttp web application.:
        """

        # setup API documentation
        setup_swagger(self.app,
                      description=self.description,
                      title=self.title,
                      api_version=self.api_version,
                      contact=self.contact)

        for handler in self.startup_handlers:
            try:
                handler()
            except Exception as exc:
                self.logger.exception(exc)

        self.srv = await self.loop.create_server(
            self.app.make_handler(
                access_log_format='%r %s',
                access_log=self.logger,
                access_log_class=self.access_log_class,
                logger=self.logger),
            address,
            port)
Esempio n. 11
0
async def init(loop):
    app = web.Application(loop=loop)

    # Configure default CORS settings.
    cors = aiohttp_cors.setup(app,
                              defaults={
                                  "*":
                                  aiohttp_cors.ResourceOptions(
                                      allow_credentials=True,
                                      expose_headers="*",
                                      allow_headers="*",
                                  )
                              })

    # Routes
    #app.router.add_route('*', '/', IndexView)
    #app.router.add_route('*', '/{uuid}', TodoView)
    # Explicitly add individual methods, see https://github.com/aio-libs/aiohttp-cors/issues/41
    cors.add(app.router.add_route('get', '/todos/', IndexView))
    cors.add(app.router.add_route('post', '/todos/', IndexView))
    cors.add(app.router.add_route('delete', '/todos/', IndexView))
    cors.add(
        app.router.add_route('get', '/todos/{uuid}', TodoView, name='todo'))
    cors.add(app.router.add_route('patch', '/todos/{uuid}', TodoView))
    cors.add(app.router.add_route('delete', '/todos/{uuid}', TodoView))

    # Config
    setup_swagger(app,
                  swagger_url="/api/v1/doc",
                  swagger_from_file="swagger.yaml")
    logger.info("Starting server at %s:%s", IP, PORT)
    srv = await loop.create_server(app.make_handler(), IP, PORT)
    return srv
Esempio n. 12
0
def setup_routes(app: web.Application):
    for route in app_routes:
        app.router.add_route(*route)

    setup_swagger(app,
                  swagger_from_file=os.path.join(BASE_DIR, 'docs/'
                                                 'swagger.yaml'))
Esempio n. 13
0
def Application(*args,
                db,
                swagger_yml: str,
                swagger_url: str = None,
                base_url: str = None,
                **kwargs):
    app = web.Application(*args, **kwargs)

    base_url = base_url or ""
    cors = aiohttp_cors.setup(
        app,
        defaults={
            "*":
            aiohttp_cors.ResourceOptions(
                allow_credentials=True,
                expose_headers="*",
                allow_headers="*",
            )
        },
    )
    cors.add(app.router.add_view(base_url + "/kanji", KanjiListView(db=db)))
    cors.add(app.router.add_view(base_url + "/kanji/{kanji}",
                                 KanjiView(db=db)))

    aiohttp_swagger.setup_swagger(app,
                                  swagger_from_file=swagger_yml,
                                  swagger_url=swagger_url)

    return app
Esempio n. 14
0
def setup_rest(app: web.Application):
    settings: RestSettings = get_plugin_settings(app)
    is_diagnostics_enabled: bool = (app[APP_SETTINGS_KEY].WEBSERVER_DIAGNOSTICS
                                    is not None)

    spec_path = get_openapi_specs_path(api_version_dir=API_VTAG)

    # validated openapi specs
    app[APP_OPENAPI_SPECS_KEY] = specs = load_openapi_specs(spec_path)

    # version check
    base_path = openapi.get_base_path(specs)
    major, *_ = specs.info.version

    if f"/v{major}" != base_path:
        raise ValueError(
            f"REST API basepath {base_path} does not fit openapi.yml version {specs.info.version}"
        )

    if api_version_prefix != f"v{major}":
        raise ValueError(
            f"__version__.api_version_prefix {api_version_prefix} does not fit openapi.yml version {specs.info.version}"
        )

    # basic routes
    app.add_routes(rest_handlers.routes)
    if not is_diagnostics_enabled:
        # NOTE: the healthcheck route is normally in diagnostics, but
        # if disabled, this plugin adds a simple version of it
        app.add_routes([
            web.get(
                path=f"/{api_version_prefix}/health",
                handler=rest_handlers.check_running,
                name="check_health",
            )
        ])

    # middlewares
    # NOTE: using safe get here since some tests use incomplete configs
    app.middlewares.extend([
        error_middleware_factory(
            api_version_prefix,
            log_exceptions=not is_diagnostics_enabled,
        ),
        envelope_middleware_factory(api_version_prefix),
    ])

    # Adds swagger doc UI
    #  - API doc at /dev/doc (optional, e.g. for testing since it can be heavy)
    #  - NOTE: avoid /api/* since traeffik uses for it's own API
    #
    log.debug("OAS loaded from %s ", spec_path)
    if settings.REST_SWAGGER_API_DOC_ENABLED:
        setup_swagger(
            app,
            swagger_url="/dev/doc",
            swagger_from_file=str(spec_path),
            ui_version=3,
        )
Esempio n. 15
0
def create_app():
    app = web.Application()

    register_routes(app)
    setup_swagger(app,
                  swagger_from_file=os.path.join(os.path.dirname(__file__),
                                                 'api.yaml'))

    return app
Esempio n. 16
0
 def start(self):
     self._logger.info(
         f'Starting HTTP server on {self._address}:{self._port}')
     setup_swagger(self._app)
     web.run_app(self._app,
                 host=self._address,
                 port=self._port,
                 reuse_address=True,
                 reuse_port=True)
Esempio n. 17
0
def setup(app: web.Application, *, swagger_doc_enabled: bool = True):
    # ----------------------------------------------
    # TODO: temporary, just to check compatibility between
    # trafaret and pydantic schemas
    cfg = assert_valid_config(app)
    # ---------------------------------------------

    api_version_dir = cfg["version"]
    spec_path = get_openapi_specs_path(api_version_dir)

    # validated openapi specs
    app[APP_OPENAPI_SPECS_KEY] = specs = load_openapi_specs(spec_path)

    # version check
    base_path = openapi.get_base_path(specs)
    major, *_ = specs.info.version

    if f"/v{major}" != base_path:
        raise ValueError(
            f"REST API basepath {base_path} does not fit openapi.yml version {specs.info.version}"
        )

    if api_version_prefix != f"v{major}":
        raise ValueError(
            f"__version__.api_version_prefix {api_version_prefix} does not fit openapi.yml version {specs.info.version}"
        )

    # diagnostics routes
    routes = rest_routes.create(specs)
    app.router.add_routes(routes)

    # middlewares
    # NOTE: using safe get here since some tests use incomplete configs
    is_diagnostics_enabled = get_diagnostics_config(app).get("enabled", False)
    app.middlewares.extend(
        [
            error_middleware_factory(
                api_version_prefix,
                log_exceptions=not is_diagnostics_enabled,
            ),
            envelope_middleware_factory(api_version_prefix),
        ]
    )

    # Adds swagger doc UI
    #  - API doc at /dev/doc (optional, e.g. for testing since it can be heavy)
    #  - NOTE: avoid /api/* since traeffik uses for it's own API
    #
    log.debug("OAS loaded from %s ", spec_path)
    if swagger_doc_enabled:
        setup_swagger(
            app,
            swagger_url="/dev/doc",
            swagger_from_file=str(spec_path),
            ui_version=3,
        )
Esempio n. 18
0
async def create_service(config: dict):
    service = web.Application()
    service['config'] = config
    service.on_startup.append(add_redis)
    service.on_cleanup.append(dispose_redis)
    service.add_routes([web.post('/database', feel_storage),
                        web.get('/convert', convert)])

    setup_swagger(service)

    return service
Esempio n. 19
0
def setup_api(app):
    # routing
    router = app.router
    prefix = "/api/v{}".format(__version__)

    router.add_post(prefix+'/login', login, name='login')
    router.add_get(prefix+'/logout', logout, name='logout')
    router.add_get(prefix+'/ping', ping, name='ping')

    # middlewares
    setup_swagger(app, swagger_url=prefix+"/doc")
Esempio n. 20
0
    def run(self, interface: Interface):
        app = web.Application()
        create_interface_routes(app, interface)
        create_schema_route(app, interface)
        create_misc_routes(app)
        setup_swagger(app, swagger_url="/apidocs", ui_version=3)

        rlogger.debug('Running aiohttp on %s:%s', HTTPServerConfig.host,
                      HTTPServerConfig.port)
        web.run_app(app,
                    host=HTTPServerConfig.host,
                    port=HTTPServerConfig.port)
Esempio n. 21
0
async def init_func(argv=None):
    middlewares = list()
    if is_xray_on():
        xray_recorder.configure(service="translation-api",
                                sampling=False,
                                context=AsyncContext(),
                                daemon_address="xray-aws-xray:2000")
        middlewares.append(xray_middleware)
    app = aiohttp.web.Application(middlewares=middlewares)
    app.add_routes([aiohttp.web.get('/translate', handle)])
    setup_swagger(app)
    return app
Esempio n. 22
0
def get_app(db):
    app = web.Application(client_max_size=0)
    app['objects'] = db

    app.on_cleanup.append(close_db)

    for ROUTE in ROUTES:
        app.router.add_route(*ROUTE)

    setup_swagger(app, swagger_url="/api/docs/")

    return app
Esempio n. 23
0
def run(
    main: Coroutine,
    path: str,
    app: Optional[web.Application] = None,
    **server_kwargs,
) -> None:
    """Start the webserver and the entrypoint logic passed in as ``main``.

    Args:
        main: The entrypoint for the service's logic, in the form of a coroutine.
        path: The path to the service's configuration file on disk.
        app: An existing web application object, if available.
        server_kwargs: Variable number of ``kwargs`` to pass to
                       :func:`aiohttp.web.run_app`.
    Raises:
        DuplicateRouteError: A user-supplied route conflicts with one of the default
                             :doc:`routes<./routes>`.
        ValueError: ``main`` is not a proper coroutine.
    """
    logging.basicConfig(
        format="%(levelname)s %(asctime)s %(filename)s:%(lineno)d] %(message)s",
        level=logging.INFO,
        datefmt="%Y-%m-%d %H:%M:%S",
    )

    if not asyncio.coroutines.iscoroutine(main):
        raise ValueError(f"A coroutine was expected, got {main}")

    # Create web application object and shutdown event
    if app is None:
        app = web.Application(middlewares=[error_middleware])
    app["main"] = main
    app["path"] = path
    app["shutdown_event"] = asyncio.Event()

    # Initialize the endpoints for the HTTP server
    try:
        app.add_routes(routes)
    except RuntimeError:
        app["main"].close()
        resources = [(r.method, r.path) for r in routes
                     if isinstance(r, web.RouteDef)]
        raise DuplicateRouteError(
            f"A user-supplied route conflicts with a pre-registered route: {resources}"
        )

    # Document the endpoints with OpenAPI
    setup_swagger(app, ui_version=3)

    # Add background tasks
    app.on_startup.append(on_startup)
    app.on_cleanup.append(on_cleanup)
    web.run_app(app, **server_kwargs)
Esempio n. 24
0
def setup_routes(app):
    app.router.add_get('/', index, name='index')
    app.router.add_post('/api/submit-job', submit_job, name='submit-job')
    app.router.add_get('/api/job-status/{job_id:[A-Za-z0-9_-]+}',
                       job_status,
                       name='job-status')
    app.router.add_get('/api/jobs-statuses',
                       jobs_statuses,
                       name='jobs-statuses')
    app.router.add_get('/api/job-result/{job_id:[A-Za-z0-9_-]+}',
                       job_result,
                       name='job-result')
    app.router.add_get('/api/rnacentral-databases',
                       rnacentral_databases,
                       name='rnacentral-databases')
    app.router.add_get('/api/job-results-urs-list/{job_id:[A-Za-z0-9_-]+}',
                       job_results_urs_list,
                       name='job-results-urs-list')
    app.router.add_get('/api/facets/{job_id:[A-Za-z0-9_-]+}',
                       facets,
                       name='facets')
    app.router.add_get('/api/facets-search/{job_id:[A-Za-z0-9_-]+}',
                       facets_search,
                       name='facets-search')
    app.router.add_get('/api/list-rnacentral-ids/{job_id:[A-Za-z0-9_-]+}',
                       list_rnacentral_ids,
                       name='list-rnacentral-ids')
    app.router.add_post('/api/post-rnacentral-ids/{job_id:[A-Za-z0-9_-]+}',
                        post_rnacentral_ids,
                        name='post-rnacentral-ids')
    app.router.add_get('/api/consumers-statuses',
                       consumers_statuses,
                       name='consumers-statuses')
    app.router.add_get('/api/show-searches',
                       show_searches,
                       name='show-searches')
    app.router.add_get('/api/infernal-status/{job_id:[A-Za-z0-9_-]+}',
                       infernal_status,
                       name='infernal-status')
    app.router.add_get('/api/infernal-result/{job_id:[A-Za-z0-9_-]+}',
                       infernal_job_result,
                       name='infernal-job-result')
    app.router.add_patch('/api/r2dt/{job_id:[A-Za-z0-9_-]+}',
                         r2dt,
                         name='r2dt')
    setup_static_routes(app)

    # setup swagger documentation
    setup_swagger(app,
                  swagger_url="api/doc",
                  title="RNAcentral sequence similarity search",
                  description="")
Esempio n. 25
0
def create_app() -> web.Application:
    """
    Application factory function. It does the following:
        1. Create a new application instance.
        2. Initializes the global DB_ENGINE constant variable.
        3. Sets up routing for the application instance.
        4. Sets up the Swagger plugin.
        5. Returns the newly created application instance.

    :return: web.Application instance
    """
    ###
    # Set the context for the I/O Loop
    #
    loop = asyncio.get_event_loop()
    loop.set_task_factory(context.task_factory)

    ###
    # Create an app instance and do the following:
    #   1. Initialize its config.
    #   2. Prepare its on-startup, on-cleanup and on-shutdown signals.
    #
    _app = web.Application(
        logger=_logger,
        middlewares=[
            sentry_middleware_factory(),
            request_context_middleware,
        ],
        loop=loop,
    )
    _app['config'] = get_config()

    _app.on_startup.append(on_app_startup)
    _app.on_cleanup.append(on_app_cleanup)
    _app.on_shutdown.append(on_app_shutdown)

    ###
    # Setup views and routes
    #
    setup_routes(_app)

    ###
    # Setup the swagger /docs endpoint.
    #
    this_modules_path = Path(__file__).parent.absolute()
    api_v1_0_swagger_doc_path = str(
        PurePath(this_modules_path, "docs/swagger-v1.0.yaml"))
    setup_swagger(_app,
                  swagger_url="/api/v1.0/docs",
                  swagger_from_file=api_v1_0_swagger_doc_path)

    return _app
Esempio n. 26
0
async def on_start_app(app):
    config = app['config']
    app['db'] = await asyncpgsa.create_pool(dsn=config['database_uri'])
    app['smtp'] = aiosmtplib.SMTP(
        hostname=config['smtp']['hostname'],
        port=config['smtp']['port']
    )
    setup_swagger(
        app=app,
        swagger_url='/api-doc',
        swagger_info=app['swagger_dict'],
        api_base_url='/api/',
    )
Esempio n. 27
0
def create_app(loop):
    app = web.Application(loop=loop)
    settings = Settings()
    app.update(
        name='app',
        settings=settings
    )

    setup_routes(app)
    setup_swagger(
        app, swagger_from_file=os.path.join(BASE_DIR, 'swagger.yaml')
    )
    return app
Esempio n. 28
0
def build_app(loop=None):
    app = web.Application(loop=loop, middlewares=get_middlewares())

    app.on_startup.append(start_plugins)
    app.on_cleanup.append(stop_plugins)

    setup_swagger(app,
                  swagger_url='/docs',
                  swagger_from_file="docs/swagger.yaml")

    register_routes(app)

    return app
Esempio n. 29
0
def main():
    app = web.Application()
    app.router.add_routes(routes)

    client = MongoClient()
    app['mongo'] = client
    app['dispatcher'] = Dispatcher(client)
    app.on_startup.append(on_startup)

    setup_swagger(app)

    context = prepare_ssl()
    web.run_app(app, host=IP, port=PORT, ssl_context=context)
Esempio n. 30
0
def main(prefix_name: str = 'mgate'):
    # set uvloop
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
    # get event-loop
    loop = asyncio.get_event_loop()

    # init settings
    init_settings()

    # create web application
    app = web.Application(middlewares=[filter_errors_request],
                          loop=loop,
                          debug=get_dev_mode(),
                          client_max_size=1024**2 * 64)
    # add Headers for request
    app.on_response_prepare.append(on_prepare)

    # set settings for DBManager
    DBManager().set_settings(
        dict(user=config.get('DB', 'user'),
             password=config.get('DB', 'password'),
             database=config.get('DB', 'database'),
             host=config.get('DB', 'host'),
             port=config.get('DB', 'port')))
    # initial connection-poll in DBManager
    loop.run_until_complete(loop.create_task(DBManager().init_pool()))

    # add routes
    setup_routes(app)

    # get url for run web-app
    bind_url = urlparse(config.get('PUBLIC_API', 'bind'))

    # run swagger
    setup_swagger(app,
                  swagger_url='/api/docs',
                  title='Travel Points docs',
                  description='',
                  api_version='0.1',
                  contact='*****@*****.**')

    # run web application
    try:
        web.run_app(app,
                    host=bind_url.hostname,
                    port=bind_url.port,
                    reuse_address=True,
                    reuse_port=True,
                    shutdown_timeout=1)
    finally:
        loop.close()