Example #1
0
def places():
    """
    Function called when user posts or gets to /places.

    :return: This function will either return category statistics or poi information within a given
    geometry. Depending on GET or POST it will prepare the payload accordingly.
    :type: string
    """

    if request.method == 'POST':

        if 'application/json' in request.headers['Content-Type'] and request.is_json:

            all_args = request.get_json(silent=True)

            raw_request = copy.deepcopy(all_args)

            if all_args is None:
                raise api_exceptions.InvalidUsage(status_code=500, error_code=4000)

            try:
                schema(all_args)
            except MultipleInvalid as error:
                raise api_exceptions.InvalidUsage(status_code=500, error_code=4000, message=str(error))
            # query stats
            if all_args['request'] == 'list':
                r = Response(json.dumps(categories_tools.categories_object), mimetype='application/json; charset=utf-8')
                return r

            if 'filters' in all_args and 'category_group_ids' in all_args['filters']:
                all_args['filters']['category_ids'] = categories_tools.unify_categories(all_args['filters'])

            if 'limit' not in all_args:
                all_args['limit'] = ops_settings['response_limit']

            if 'geometry' not in all_args:
                raise api_exceptions.InvalidUsage(status_code=500, error_code=4002)

            are_required_geom_present(all_args['geometry'])

            # check restrictions and parse geometry
            all_args['geometry'] = parse_geometries(all_args['geometry'])

            features = request_pois(all_args)

            query_info = QueryInfo(raw_request).__dict__

            features["information"] = query_info

            # query pois
            r = Response(json.dumps(features), mimetype='application/json; charset=utf-8')
            return r

    else:

        raise api_exceptions.InvalidUsage(status_code=500, error_code=4006)
Example #2
0
def are_required_geom_present(geometry):
    """
    Checks if enough geometry options are are present in request.
    :param geometry: Geometry parameters from  post request
    """
    if 'geojson' not in geometry and 'bbox' not in geometry:
        raise api_exceptions.InvalidUsage(status_code=500, error_code=4003)
Example #3
0
def are_required_keys_present(filters):
    """
    Checks if category group ids of category ids are present in request.
    :param filters: Request parameters from get or post request
    """
    if 'category_group_ids' not in filters and 'category_ids' not in filters:
        raise api_exceptions.InvalidUsage(status_code=500, error_code=4001)
Example #4
0
def check_validity(geojson):
    """
    Checks if geojson is valid, throws exception otherwise.
    :param geojson: geojson object
    :return: will return the geo
    """
    if geojson.is_valid:
        return geojson
    else:
        raise api_exceptions.InvalidUsage(status_code=500, error_code=4007, message='{} {}'.format(
            "geojson", geojson.is_valid))
Example #5
0
def parse_geometries(geometry):
    """
    Parses the geometries to geojson objects and checks them for validity.
    :param geometry: Request parameters from get or post request
    :return: returns processed request parameters
    """
    # parse radius
    if 'buffer' not in geometry:
        geometry['buffer'] = 0

    # parse geojson
    if 'geojson' in geometry:

        s = json.dumps(geometry['geojson'])
        # Convert to geojson.geometry
        try:
            g1 = geojson.loads(s)
        except ValueError as e:
            raise api_exceptions.InvalidUsage(status_code=500,
                                              error_code=4007,
                                              message=str(e))

        # Feed to shape() to convert to shapely.geometry.polygon.Polygon
        # This will invoke its __geo_interface__ (https://gist.github.com/sgillies/2217756)
        try:
            g2 = shape(g1)
        except ValueError as e:
            raise api_exceptions.InvalidUsage(status_code=500,
                                              error_code=4007,
                                              message=str(e))
        except AttributeError as e:
            raise api_exceptions.InvalidUsage(status_code=500,
                                              error_code=4007,
                                              message=str(e))

        # parse geom if valid
        geojson_obj = check_validity(g2)

        if geojson_obj.geom_type == 'Point':
            check_for_buffer(geometry,
                             ops_settings['maximum_search_radius_for_points'])

        elif geojson_obj.geom_type == 'LineString':
            check_for_buffer(
                geometry,
                ops_settings['maximum_search_radius_for_linestrings'])

            # check if linestring not too long
            length = transform_geom(geojson_obj, 'epsg:4326',
                                    'epsg:3857').length
            if length > ops_settings['maximum_linestring_length']:
                raise api_exceptions.InvalidUsage(
                    status_code=500,
                    error_code=4005,
                    message=
                    'Your linestring geometry is too long ({} meters), check the server restrictions.'
                    .format(length))

        elif geojson_obj.geom_type == 'Polygon' or geojson_obj.geom_type == 'MultiPolygon':

            check_for_buffer(
                geometry, ops_settings['maximum_search_radius_for_polygons'])

            # check if area not too large
            area = transform_geom(geojson_obj, 'epsg:4326', 'epsg:3857').area
            if area > ops_settings['maximum_area']:
                raise api_exceptions.InvalidUsage(
                    message=
                    'Your polygon geometry is too large ({} square meters), check the server '
                    'restrictions.'.format(area),
                    status_code=500,
                    error_code=4008)

        else:
            # type not supported
            raise api_exceptions.InvalidUsage(
                error_code=4007,
                message='GeoJSON type {} not supported'.format(
                    geojson_obj.geom_type),
                status_code=500)

        geometry['geom'] = geojson_obj

    # parse bbox, can be provided additionally to geometry
    if 'bbox' in geometry:

        try:
            geojson_obj = MultiPoint(parse_geometry(geometry['bbox']))
        except ValueError as e:
            raise api_exceptions.InvalidUsage(status_code=500,
                                              error_code=4007,
                                              message=str(e))

        geometry['bbox'] = check_validity(geojson_obj).envelope

        # print(geometry['bbox'].wkt)

        # check if area not too large
        area = transform_geom(geometry['bbox'], 'epsg:4326', 'epsg:3857').area
        if area > ops_settings['maximum_area']:
            raise api_exceptions.InvalidUsage(
                error_code=4008,
                status_code=500,
                message='Your polygon geometry is too large ({} square meters), '
                'check the server restrictions.'.format(area))

    return geometry
Example #6
0
def check_for_buffer(geometry, maximum_search_radius):
    if 'buffer' not in geometry:
        raise api_exceptions.InvalidUsage(status_code=500, error_code=4004)

    if not validate_limit(int(geometry['buffer']), maximum_search_radius):
        raise api_exceptions.InvalidUsage(status_code=500, error_code=4008)
Example #7
0
def places():
    """
    Function called when user posts or gets to /places.

    :return: This function will either return category statistics or poi information within a given
    geometry. Depending on GET or POST it will prepare the payload accordingly.
    :type: string
    """

    if request.method == 'POST':

        if request.is_json:

            all_args = request.get_json(silent=True)

            raw_request = copy.deepcopy(all_args)

            if all_args is None:
                raise api_exceptions.InvalidUsage(status_code=400,
                                                  error_code=4000)

            try:
                schema(all_args)
            except MultipleInvalid as error:
                raise api_exceptions.InvalidUsage(status_code=400,
                                                  error_code=4000,
                                                  message=str(error))
            # query stats
            if all_args['request'] == 'list':
                r = Response(json.dumps(categories_tools.categories_object),
                             mimetype='application/json; charset=utf-8')
                return r

            if 'filters' in all_args and 'category_group_ids' in all_args[
                    'filters']:
                all_args['filters'][
                    'category_ids'] = categories_tools.unify_categories(
                        all_args['filters'])

            if 'limit' not in all_args:
                all_args['limit'] = ops_settings['response_limit']

            if 'geometry' not in all_args:
                raise api_exceptions.InvalidUsage(status_code=400,
                                                  error_code=4002)

            are_required_geom_present(all_args['geometry'])

            # check restrictions and parse geometry
            all_args['geometry'] = parse_geometries(all_args['geometry'])
            features = []
            gj = all_args['geometry'].get('geojson')
            if gj and gj.get('type') == 'MultiPolygon':
                polygons = list(all_args['geometry']['geom'])

                for polygon in polygons:
                    all_args['geometry']['geom'] = polygon
                    tmp = request_pois(all_args)
                    query_info = QueryInfo(raw_request).__dict__
                    tmp["information"] = query_info
                    features.append(tmp)

            else:
                tmp = request_pois(all_args)
                query_info = QueryInfo(raw_request).__dict__
                tmp["information"] = query_info
                features.append(tmp)

            # query pois
            r = Response(json.dumps(features),
                         mimetype='application/json; charset=utf-8')
            return r

        else:
            with open("osm/invalid-requests.log", "a") as f:
                time = datetime.now()
                req = request.data.decode().strip().replace("\n", "").replace(
                    " ", "")
                f.write(f"{time} {request.remote_addr}: - {req}\n")
                f.close()

            raise api_exceptions.InvalidUsage(status_code=400, error_code=4009)

    else:

        raise api_exceptions.InvalidUsage(status_code=400, error_code=4006)