diff --git a/prez/routers/curie.py b/prez/routers/curie.py index 0b6a44be..d93df57e 100644 --- a/prez/routers/curie.py +++ b/prez/routers/curie.py @@ -1,6 +1,7 @@ -from fastapi import APIRouter +from fastapi import APIRouter, HTTPException, status from fastapi.responses import PlainTextResponse from rdflib import URIRef +from rdflib.term import _is_valid_uri from prez.services.curie_functions import get_uri_for_curie_id, get_curie_id_for_uri @@ -11,15 +12,43 @@ "/identifier/curie/{iri:path}", summary="Get the IRI's CURIE identifier", response_class=PlainTextResponse, + responses={ + status.HTTP_400_BAD_REQUEST: {"content": {"application/json": {}}}, + status.HTTP_500_INTERNAL_SERVER_ERROR: {"content": {"application/json": {}}}, + }, ) def get_curie_route(iri: str): - return get_curie_id_for_uri(URIRef(iri)) + if not _is_valid_uri(iri): + raise HTTPException(status.HTTP_400_BAD_REQUEST, f"Invalid characters in {iri}") + try: + return get_curie_id_for_uri(URIRef(iri)) + except ValueError as err: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, f"Error processing IRI {iri}" + ) from err + except Exception as err: + raise HTTPException( + status.HTTP_500_INTERNAL_SERVER_ERROR, + f"Unhandled server error for IRI {iri}", + ) from err @router.get( "/identifier/iri/{curie}", summary="Get the CURIE identifier's fully qualified IRI", response_class=PlainTextResponse, + responses={ + status.HTTP_400_BAD_REQUEST: {"content": {"application/json": {}}}, + status.HTTP_500_INTERNAL_SERVER_ERROR: {"content": {"application/json": {}}}, + }, ) def get_iri_route(curie: str): - return get_uri_for_curie_id(curie) + try: + return get_uri_for_curie_id(curie) + except ValueError as err: + raise HTTPException(status.HTTP_400_BAD_REQUEST, str(err)) from err + except Exception as err: + raise HTTPException( + status.HTTP_500_INTERNAL_SERVER_ERROR, + f"Unhandled server error for curie {curie}", + ) from err diff --git a/tests/curies/test_curie_endpoint.py b/tests/curies/test_curie_endpoint.py new file mode 100644 index 00000000..2909374a --- /dev/null +++ b/tests/curies/test_curie_endpoint.py @@ -0,0 +1,44 @@ +import pytest +from fastapi.testclient import TestClient + +from prez.app import app + + +@pytest.fixture +def client() -> TestClient: + testclient = TestClient(app) + + # Make a request for the following IRI to ensure + # the curie is available in the 'test_curie' test. + iri = "http://example.com/namespace/test" + response = testclient.get(f"/identifier/curie/{iri}") + assert response.status_code == 200 + assert response.text == "nmspc:test" + + return testclient + + +@pytest.mark.parametrize( + "iri, expected_status_code", + [ + ["d", 400], + ["http://!", 400], + ["http://example.com/namespace", 200], + ], +) +def test_iri(iri: str, expected_status_code: int, client: TestClient): + response = client.get(f"/identifier/curie/{iri}") + assert response.status_code == expected_status_code + + +@pytest.mark.parametrize( + "curie, expected_status_code", + [ + ["d", 400], + ["ns1", 400], + ["nmspc:test", 200], + ], +) +def test_curie(curie: str, expected_status_code: int, client: TestClient): + response = client.get(f"/identifier/iri/{curie}") + assert response.status_code == expected_status_code