Skip to content

Commit

Permalink
fix: add/raise appropriate error for /cql endpoint where no filter is…
Browse files Browse the repository at this point in the history
… provided.
  • Loading branch information
recalcitrantsupplant committed Jan 20, 2025
1 parent e1b9a5e commit 4208c68
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 28 deletions.
5 changes: 3 additions & 2 deletions prez/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
NoEndpointNodeshapeException,
NoProfilesException,
PrefixNotFoundException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)
from prez.middleware import create_validate_header_middleware
from prez.repositories import OxrdflibRepo, PyoxigraphRepo, RemoteSparqlRepo
Expand Down Expand Up @@ -59,7 +59,7 @@
catch_no_endpoint_nodeshape_exception,
catch_no_profiles_exception,
catch_prefix_not_found_exception,
catch_uri_not_found_exception,
catch_uri_not_found_exception, catch_missing_filter_query_param,
)
from prez.services.generate_profiles import create_profiles_graph
from prez.services.prez_logging import setup_logger
Expand Down Expand Up @@ -181,6 +181,7 @@ def assemble_app(
NoProfilesException: catch_no_profiles_exception,
InvalidSPARQLQueryException: catch_invalid_sparql_query,
NoEndpointNodeshapeException: catch_no_endpoint_nodeshape_exception,
MissingFilterQueryError: catch_missing_filter_query_param
},
**kwargs
)
Expand Down
51 changes: 28 additions & 23 deletions prez/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)
from prez.exceptions.model_exceptions import (
NoEndpointNodeshapeException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)
from prez.enums import SearchMethod
from prez.models.query_params import QueryParams
Expand Down Expand Up @@ -147,6 +147,29 @@ async def load_annotations_data_to_oxigraph(store: Store):
store.load(file_bytes, "application/n-triples")



async def get_endpoint_uri_type(
request: Request,
system_repo: Repo = Depends(get_system_repo),
) -> tuple[URIRef, URIRef]:
"""
Returns the URI of the endpoint and its type (ObjectEndpoint or ListingEndpoint)
"""
endpoint_uri = URIRef(request.scope.get("route").name)
ep_type_fs = await get_classes_single(endpoint_uri, system_repo)
ep_types = list(ep_type_fs)

# Iterate over each item in ep_types
for ep_type in ep_types:
# Check if the current ep_type is either ObjectEndpoint or ListingEndpoint
if ep_type in [ONT.ObjectEndpoint, ONT.ListingEndpoint]:
return endpoint_uri, ep_type
raise ValueError(
"Endpoint must be declared as either a 'https://prez.dev/ont/ObjectEndpoint' or a "
"'https://prez.dev/ont/ListingEndpoint' in order for the appropriate profile to be determined."
)


async def cql_post_parser_dependency(
request: Request,
queryable_props: list = Depends(get_queryable_props),
Expand All @@ -168,6 +191,7 @@ async def cql_post_parser_dependency(
async def cql_get_parser_dependency(
query_params: QueryParams = Depends(),
queryable_props: list = Depends(get_queryable_props),
endpoint_uri_type: str = Depends(get_endpoint_uri_type),
) -> CQLParser:
if query_params._filter:
try:
Expand All @@ -186,6 +210,9 @@ async def cql_get_parser_dependency(
raise HTTPException(
status_code=400, detail="Invalid CQL format: Parsing failed."
)
elif endpoint_uri_type[0] == URIRef('https://prez.dev/endpoint/extended-ogc-records/cql-get'):
raise MissingFilterQueryError("filter query parameter with a valid CQL JSON expression must be provided when "
"using the /cql endpoint.")


async def get_jena_fts_shacl_predicates(system_repo: Repo):
Expand Down Expand Up @@ -268,28 +295,6 @@ async def generate_search_query(
return search_query


async def get_endpoint_uri_type(
request: Request,
system_repo: Repo = Depends(get_system_repo),
) -> tuple[URIRef, URIRef]:
"""
Returns the URI of the endpoint and its type (ObjectEndpoint or ListingEndpoint)
"""
endpoint_uri = URIRef(request.scope.get("route").name)
ep_type_fs = await get_classes_single(endpoint_uri, system_repo)
ep_types = list(ep_type_fs)

# Iterate over each item in ep_types
for ep_type in ep_types:
# Check if the current ep_type is either ObjectEndpoint or ListingEndpoint
if ep_type in [ONT.ObjectEndpoint, ONT.ListingEndpoint]:
return endpoint_uri, ep_type
raise ValueError(
"Endpoint must be declared as either a 'https://prez.dev/ont/ObjectEndpoint' or a "
"'https://prez.dev/ont/ListingEndpoint' in order for the appropriate profile to be determined."
)


async def generate_concept_hierarchy_query(
request: Request,
endpoint_uri_type: tuple[URIRef, URIRef] = Depends(get_endpoint_uri_type),
Expand Down
9 changes: 9 additions & 0 deletions prez/exceptions/model_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,12 @@ def __init__(self, ep_uri: str, hierarchy_level: int):
f"{hierarchy_level}, and parent URI"
)
super().__init__(self.message)


class MissingFilterQueryError(ValueError):
"""
Raised when a filter query is missing.
"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
4 changes: 2 additions & 2 deletions prez/routers/ogc_features_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
NoEndpointNodeshapeException,
NoProfilesException,
PrefixNotFoundException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)
from prez.models.ogc_features import OGCFeaturesLandingPage, generate_landing_page_links
from prez.models.query_params import QueryParams
Expand All @@ -44,7 +44,7 @@
catch_no_endpoint_nodeshape_exception,
catch_no_profiles_exception,
catch_prefix_not_found_exception,
catch_uri_not_found_exception,
catch_uri_not_found_exception, catch_missing_filter_query_param,
)
from prez.services.listings import ogc_features_listing_function
from prez.services.objects import ogc_features_object_function
Expand Down
13 changes: 12 additions & 1 deletion prez/services/exception_catchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
NoEndpointNodeshapeException,
NoProfilesException,
PrefixNotFoundException,
URINotFoundException,
URINotFoundException, MissingFilterQueryError,
)


Expand Down Expand Up @@ -90,3 +90,14 @@ async def catch_no_endpoint_nodeshape_exception(
"detail": exc.message,
},
)

async def catch_missing_filter_query_param(
request: Request, exc: MissingFilterQueryError
):
return JSONResponse(
status_code=400,
content={
"error": "Bad Request",
"detail": exc.message,
},
)

0 comments on commit 4208c68

Please sign in to comment.