Skip to content

Commit 4bd1ad4

Browse files
committed
error handling update for parse POST
1 parent 1028d5b commit 4bd1ad4

File tree

2 files changed

+67
-50
lines changed

2 files changed

+67
-50
lines changed

src/handlers/api.py

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -688,22 +688,22 @@ async def get(self, *args, **kwargs):
688688

689689
class MetaKGParserHandler(BaseHandler):
690690
"""
691-
Handles parsing of SmartAPI metadata from a given URL or request body.
692-
693-
This handler processes SmartAPI metadata and returns structured,
694-
cleaned results based on the specified query parameters.
695-
696-
Supported HTTP methods:
697-
- **GET**: Parses metadata from a provided URL.
698-
- **POST**: Parses metadata from the request body.
699-
700-
Query Parameters:
701-
- `url` (str, required): The URL of the SmartAPI metadata to parse.
702-
Maximum length: 1000 characters.
703-
- `api_details` (bool, optional, default: `False`):
704-
Whether to return detailed API information.
705-
- `bte` (bool, optional, default: `False`):
706-
Whether to include BTE (BioThings Explorer) specific metadata.
691+
Handles parsing of SmartAPI metadata from a given URL or request body.
692+
693+
This handler processes SmartAPI metadata and returns structured,
694+
cleaned results based on the specified query parameters.
695+
696+
Supported HTTP methods:
697+
- **GET**: Parses metadata from a provided URL.
698+
- **POST**: Parses metadata from the request body.
699+
700+
Query Parameters:
701+
- `url` (str, required): The URL of the SmartAPI metadata to parse.
702+
Maximum length: 1000 characters.
703+
- `api_details` (bool, optional, default: `False`):
704+
Whether to return detailed API information.
705+
- `bte` (bool, optional, default: `False`):
706+
Whether to include BTE (BioThings Explorer) specific metadata.
707707
"""
708708

709709
kwargs = {
@@ -731,10 +731,8 @@ def initialize(self, *args, **kwargs):
731731
def get_filtered_api(self, api_dict):
732732
"""Extract and return filtered API information."""
733733
api_info = api_dict["api"]
734-
735-
# Convert arguments to integers for consistency
736-
bte = int(self.args.bte)
737-
api_details = int(self.args.api_details)
734+
bte = self.args.bte
735+
api_details = self.args.api_details
738736

739737
# Default structure to preserve top-level keys
740738
filtered_dict = {
@@ -797,15 +795,20 @@ async def get(self, *args, **kwargs):
797795
if not self.get_argument("url", None):
798796
raise HTTPError(400, reason="A url value is expected for the request, please provide a url.")
799797

798+
# Set initial args
800799
parser = MetaKGParser()
801800
url = self.get_argument("url")
802-
self.args.api_details = self.get_argument("api_details", False)
803-
self.args.bte = self.get_argument("bte", False)
801+
self.args.api_details = int(self.get_argument("api_details", 0))
802+
self.args.bte = int(self.get_argument("bte", 0))
804803

804+
# Get data
805805
trapi_data = parser.get_TRAPI_metadatas(data=None, url=url)
806806
nontrapi_data = parser.get_non_TRAPI_metadatas(data=None, url=url)
807807
combined_data = trapi_data + nontrapi_data
808808

809+
if not combined_data:
810+
raise HTTPError(404, reason="Metadata not found.")
811+
809812
for i, api_dict in enumerate(combined_data):
810813
filtered_api = self.get_filtered_api(api_dict)
811814
combined_data[i] = filtered_api
@@ -821,31 +824,46 @@ async def get(self, *args, **kwargs):
821824
self.write(response)
822825

823826
async def post(self, *args, **kwargs):
827+
if not self.request.body:
828+
raise HTTPError(400, reason="Request body cannot be empty.")
829+
830+
# Attempt to parse JSON body
824831
try:
825-
# Read the raw request body
826-
body = self.request.body
827-
# Parse the JSON content
828-
data = json.loads(body)
829-
parser = MetaKGParser()
830-
self.args.api_details = self.get_argument("api_details", "0")
831-
self.args.bte = self.get_argument("bte", "0")
832-
trapi_data = parser.get_TRAPI_metadatas(data=data)
833-
nontrapi_data = parser.get_non_TRAPI_metadatas(data=data)
834-
combined_data = trapi_data + nontrapi_data
835-
836-
for i, api_dict in enumerate(combined_data):
837-
filtered_api = self.get_filtered_api(api_dict)
838-
combined_data[i] = filtered_api
832+
data = json.loads(self.request.body)
833+
except json.JSONDecodeError:
834+
raise HTTPError(400, reason="Invalid JSON content in request body.")
839835

840-
response = {
841-
"took": 1,
842-
"total": len(combined_data),
843-
"max_score": 1,
844-
"hits": combined_data,
845-
}
836+
# Ensure the parsed data is a dictionary
837+
if not isinstance(data, dict):
838+
raise HTTPError(400, reason="Invalid JSON format. Expected a JSON object.")
846839

847-
self.set_header("Content-Type", "application/json")
848-
self.write(response)
840+
parser = MetaKGParser()
841+
842+
try:
843+
self.args.api_details = int(self.get_argument("api_details", 0))
844+
self.args.bte = int(self.get_argument("bte", 0))
845+
except ValueError:
846+
raise HTTPError(400, reason="Invalid query parameter value. 'api_details' and 'bte' must be integers.")
847+
848+
# Process metadata
849+
trapi_data = parser.get_TRAPI_metadatas(data=data)
850+
nontrapi_data = parser.get_non_TRAPI_metadatas(data=data)
851+
combined_data = trapi_data + nontrapi_data
849852

850-
except json.JSONDecodeError:
851-
raise ValueError("Invalid JSON content in request body.")
853+
if not combined_data:
854+
raise HTTPError(404, reason="Metadata not found.")
855+
856+
# Apply filtering
857+
for i, api_dict in enumerate(combined_data):
858+
filtered_api = self.get_filtered_api(api_dict)
859+
combined_data[i] = filtered_api
860+
861+
response = {
862+
"took": 1,
863+
"total": len(combined_data),
864+
"max_score": 1,
865+
"hits": combined_data,
866+
}
867+
868+
self.set_header("Content-Type", "application/json")
869+
self.write(response)

src/utils/metakg/parser.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class MetaKGParser:
1616
metakg_errors = None
1717

1818
def get_non_TRAPI_metadatas(self, data=None, extra_data=None, url=None):
19-
# Error Handling
2019
if not data and not url:
2120
raise HTTPError(400, reason="Either data or url value is expected for this request, please provide data or a url.")
2221
# raise ValueError("Either data or url must be provided.")
@@ -25,7 +24,7 @@ def get_non_TRAPI_metadatas(self, data=None, extra_data=None, url=None):
2524
elif url:
2625
parser = API(url=url)
2726
else:
28-
raise HTTPError(404, "Error getting metadata from provided data or url, for more info please reference: ")
27+
raise HTTPError(404, "No metadata available from provided data or url.")
2928

3029
mkg = self.extract_metakgedges(parser.metadata["operations"], extra_data=extra_data)
3130
no_nodes = len({x["subject"] for x in mkg} | {x["object"] for x in mkg})
@@ -42,7 +41,7 @@ def get_TRAPI_metadatas(self, data=None, extra_data=None, url=None):
4241
elif url:
4342
metadata_list = self.get_TRAPI_with_metakg_endpoint(url=url)
4443
else:
45-
raise HTTPError(404, "Error getting metadata from provided data or url, for more info please reference: ")
44+
raise HTTPError(404, "No metadata available from provided data or url.")
4645

4746
if isinstance(metadata_list, Exception):
4847
return metadata_list
@@ -65,7 +64,7 @@ def get_TRAPI_with_metakg_endpoint(self, data=None, url=None):
6564
try:
6665
metadata = parser.metadata
6766
except DownloadError as dl_err:
68-
raise HTTPError(400, reason="Unable to download response data with given input. Please look at your given input for any errors.")
67+
raise HTTPError(400, reason="Error fetching data from given input.")
6968
_paths = metadata.get("paths", {})
7069
_team = metadata.get("x-translator", {}).get("team")
7170

0 commit comments

Comments
 (0)