Beispiel #1
0
async def send_beacon_query_websocket(request, db_pool):
    """Send Beacon queries and respond asynchronously via websocket."""
    LOG.debug('Websocket response (async).')
    # Prepare websocket connection
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    # Task variables
    params = request.query_string  # query parameters (variant search)
    tasks = []  # requests to be done
    services = await get_services(
        db_pool)  # service urls (beacons, aggregators) to be queried
    access_token = await get_access_token(request
                                          )  # Get access token if one exists

    for service in services:
        # Generate task queue
        task = asyncio.ensure_future(
            query_service(service, params, access_token, ws=ws))
        tasks.append(task)

    # Prepare and initiate co-routines
    await asyncio.gather(*tasks)
    # Close websocket after all results have been sent
    await ws.close()

    return ws
async def query(request):
    """Forward variant query to Beacons."""
    LOG.debug('GET /query received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # For websocket
    connection_header = request.headers.get(
        'Connection',
        'default').lower().split(',')  # break down if multiple items
    connection_header = [value.strip()
                         for value in connection_header]  # strip spaces

    if 'upgrade' in connection_header and request.headers.get(
            'Upgrade', 'default').lower() == 'websocket':
        # Use asynchronous websocket connection
        # Send request for processing
        websocket = await send_beacon_query_websocket(request, db_pool)

        # Return websocket connection
        return websocket
    else:
        # User standard synchronous http
        # Send request for processing
        response = await send_beacon_query(request, db_pool)

        # Return results
        return web.json_response(response)
async def beacons(request):
    """Invalidate cached Beacons."""
    LOG.debug('DELETE /beacons received.')

    # Send request for processing
    await invalidate_cache()

    # Return confirmation
    return web.HTTPNoContent()
Beispiel #4
0
async def get_info(host_id, db_pool):
    """Return service info of self."""
    LOG.debug('Get service info of self.')

    # Take connection from the database pool
    async with db_pool.acquire() as connection:
        # Fetch service info from database
        response = await db_get_service_details(connection, id=host_id)

    return response
Beispiel #5
0
async def info(request):
    """Return service info."""
    LOG.debug('GET /info received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # Send request for processing
    response = await get_info(
        os.environ.get('HOST_ID', CONFIG.registry['host_id']), db_pool)

    # Return results
    return web.json_response(response)
async def services_delete(request):
    """DELETE request to the /user endpoint.
    Delete registered service from host.
    """
    LOG.debug('DELETE /services received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # Send request for processing
    await delete_services(request, db_pool)

    # Return confirmation
    return web.HTTPNoContent()
async def services_put(request):
    """PATCH request to the /user endpoint.
    Update service details at host.
    """
    LOG.debug('PUT /services received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # Send request for processing
    await update_service(request, db_pool)

    # Return confirmation
    return web.HTTPNoContent()
Beispiel #8
0
async def services_get(request):
    """GET request to the /services endpoint.
    Return services that are registered at host.
    """
    LOG.debug('GET /services received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # Send request for processing
    response = await get_services(request, db_pool)

    # Return results
    return web.json_response(response)
async def services_post(request):
    """POST request to the /services endpoint.
    Register a new service at host.
    """
    LOG.debug('POST /services received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # Send request for processing
    response = await register_service(request, db_pool)

    # Return confirmation and service key if no problems occurred during processing
    return web.HTTPCreated(body=json.dumps(response),
                           content_type='application/json')
Beispiel #10
0
def set_cors(app):
    """Set CORS rules."""
    LOG.debug('Applying CORS rules.')
    # Configure CORS settings, allow all domains
    cors = aiohttp_cors.setup(app,
                              defaults={
                                  "*":
                                  aiohttp_cors.ResourceOptions(
                                      allow_credentials=True,
                                      expose_headers="*",
                                      allow_headers="*",
                                  )
                              })
    # Apply CORS to endpoints
    for route in list(app.router.routes()):
        cors.add(route)
Beispiel #11
0
async def services_put(request):
    """PATCH request to the /user endpoint.
    Update service details at host.
    """
    LOG.debug('PUT /services received.')
    # Tap into the database pool
    db_pool = request.app['pool']

    # Send request for processing
    await update_service(request, db_pool)

    # Notify aggregators of changed service catalogue
    await invalidate_aggregator_caches(request, db_pool)

    # Return confirmation
    return web.HTTPNoContent()
Beispiel #12
0
async def get_services(request, db_pool):
    """Return service details."""
    LOG.debug('Return services.')

    # Parse query params from path
    service_id, params = await query_params(request)

    # Take connection from the database pool
    async with db_pool.acquire() as connection:
        # Fetch services from database
        response = await db_get_service_details(
            connection,
            id=service_id,
            service_type=params.get('serviceType', None),
            api_version=params.get('apiVersion', None),
            list_format=params.get('listFormat', 'full'))

    return response
Beispiel #13
0
async def update_service(request, db_pool):
    """Update service details."""
    LOG.debug('Update service.')
    # Get POST request body JSON as python dict
    service = await request.json()

    # Parse query params from path, mainly service_id
    service_id, params = await query_params(request)

    # Check that user specified id in path
    if service_id:
        # Take connection from the database pool
        async with db_pool.acquire() as connection:
            # Verify that given service exists
            id_found_service = await db_check_service_id(
                connection, service_id)
            if not id_found_service:
                raise web.HTTPNotFound(
                    text='No services found with given service ID.')
            # Initiate update
            await db_update_sequence(connection, service_id, service)
    else:
        raise web.HTTPBadRequest(
            text='Missing path parameter Service ID: "/services/<service_id>"')
Beispiel #14
0
async def send_beacon_query(request, db_pool):
    """Send Beacon queries and respond synchronously."""
    LOG.debug('Normal response (sync).')
    # response = web.Response()
    # await response.prepare(request)

    # Task variables
    params = request.query_string  # query parameters (variant search)
    tasks = []  # requests to be done
    services = await get_services(
        db_pool)  # service urls (beacons, aggregators) to be queried
    access_token = await get_access_token(request
                                          )  # Get access token if one exists

    for service in services:
        # Generate task queue
        task = asyncio.ensure_future(
            query_service(service, params, access_token))
        tasks.append(task)

    # Prepare and initiate co-routines
    results = await asyncio.gather(*tasks)

    return results
Beispiel #15
0
async def delete_services(request, db_pool):
    """Delete service(s)."""
    LOG.debug('Delete service(s).')

    # Parse query params from path, mainly service_id
    service_id, params = await query_params(request)

    # Delete specified service
    if service_id:
        # Take connection from the database pool
        async with db_pool.acquire() as connection:
            # # Delete specified service
            # if service_id:
            # Verify that given service_id exists
            id_found = await db_check_service_id(connection, service_id)
            if not id_found:
                raise web.HTTPNotFound(
                    text='No services found with given service ID.')
            await db_delete_services(connection, id=service_id)
            # # Delete all services
            # else:
            #     await db_delete_services(connection)
    else:
        raise web.HTTPForbidden(text='Mass deletion has been disabled.')
Beispiel #16
0
async def register_service(request, db_pool):
    """Register a new service at host."""
    LOG.debug('Register new service.')
    # Get POST request body JSON as python dict
    service = await request.json()

    # Parse query params from path, `_` denotes service_id from path param /services/{service_id}, which is not used here
    _, params = await query_params(request)

    # Response object
    response = {'message': '', 'beaconServiceKey': ''}

    if 'remote' in params:
        # This option is used at Aggregators when they do a remote registration at a Registry
        LOG.debug(f'Remote registration request to {params["remote"]}.')
        # Register self (aggregator) at remote service (registry) via self, not manually
        service_key = await remote_registration(db_pool, request,
                                                params['remote'])
        response = {
            'message':
            f'Service has been registered remotely at {params["remote"]}. Service key for updating and deleting registration included in this response, keep it safe.',
            'beaconServiceKey': service_key
        }
    else:
        LOG.debug('Local registration at host.')
        # Take connection from database pool, re-use connection for all tasks
        async with db_pool.acquire() as connection:
            # Check that the chosen service ID is not taken
            id_taken = await db_check_service_id(connection, service['id'])
            if id_taken:
                raise web.HTTPConflict(text='Service ID is taken.')
            # Register service to host
            service_key = await db_register_service(connection, service)
            response = {
                'message':
                'Service has been registered. Service key for updating and deleting registration included in this response, keep it safe.',
                'beaconServiceKey': service_key
            }

    return response
Beispiel #17
0
async def invalidate_cache():
    """Delete local Beacon cache."""
    LOG.debug('Invalidate cached Beacons.')

    await clear_cache()
    LOG.debug('Cache invalidating procedure complete.')
Beispiel #18
0
async def get_service_types():
    """Return GA4GH service types."""
    LOG.debug('Get service types.')
    return ['GA4GHRegistry', 'GA4GHBeaconAggregator', 'GA4GHBeacon']
Beispiel #19
0
async def service_types(request):
    """Return service types."""
    LOG.debug('GET /servicetypes received.')
    response = await get_service_types()
    return web.json_response(response)
Beispiel #20
0
async def index(request):
    """Greeting endpoint."""
    LOG.debug('Greeting endpoint.')
    return web.Response(text='GA4GH Beacon Registry API')