Skip to content

Commit

Permalink
feat: add search API error formatting as per specification #296
Browse files Browse the repository at this point in the history
  • Loading branch information
MRichards99 committed Feb 14, 2022
1 parent 11d59e8 commit 3a5a3e8
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
8 changes: 7 additions & 1 deletion datagateway_api/src/api_start_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pathlib import Path

from apispec import APISpec
from flask import Response
from flask_cors import CORS
from flask_restful import Api
from flask_swagger_ui import get_swaggerui_blueprint
Expand Down Expand Up @@ -55,7 +56,12 @@ class CustomErrorHandledApi(Api):
"""

def handle_error(self, e):
return str(e), e.status_code
if isinstance(e.args[0], (str, dict, tuple, Response)):
error_msg = e.args[0]
else:
error_msg = str(e)

return error_msg, e.status_code


def create_app_infrastructure(flask_app):
Expand Down
6 changes: 6 additions & 0 deletions datagateway_api/src/resources/search_api_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
get_files_count,
get_search,
get_with_pid,
search_api_error_handling,
)

log = logging.getLogger()
Expand All @@ -26,6 +27,7 @@ def get_search_endpoint(entity_name):
"""

class Endpoint(Resource):
@search_api_error_handling
def get(self):
filters = get_filters_from_query_string("search_api", entity_name)
log.debug("Filters: %s", filters)
Expand All @@ -49,6 +51,7 @@ def get_single_endpoint(entity_name):
"""

class EndpointWithID(Resource):
@search_api_error_handling
def get(self, pid):
filters = get_filters_from_query_string("search_api", entity_name)
log.debug("Filters: %s", filters)
Expand All @@ -72,6 +75,7 @@ def get_number_count_endpoint(entity_name):
"""

class CountEndpoint(Resource):
@search_api_error_handling
def get(self):
# Only WHERE included on count endpoints
filters = get_filters_from_query_string("search_api", entity_name)
Expand All @@ -96,6 +100,7 @@ def get_files_endpoint(entity_name):
"""

class FilesEndpoint(Resource):
@search_api_error_handling
def get(self, pid):
filters = get_filters_from_query_string("search_api", entity_name)
log.debug("Filters: %s", filters)
Expand All @@ -120,6 +125,7 @@ def get_number_count_files_endpoint(entity_name):
"""

class CountFilesEndpoint(Resource):
@search_api_error_handling
def get(self, pid):
# Only WHERE included on count endpoints
filters = get_filters_from_query_string("search_api", entity_name)
Expand Down
46 changes: 45 additions & 1 deletion datagateway_api/src/search_api/helpers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from functools import wraps
import json
import logging

from datagateway_api.src.common.exceptions import MissingRecordError
from datagateway_api.src.common.exceptions import (
BadRequestError,
MissingRecordError,
)
from datagateway_api.src.common.filter_order_handler import FilterOrderHandler
from datagateway_api.src.search_api.filters import (
SearchAPIIncludeFilter,
Expand All @@ -18,6 +22,46 @@
log = logging.getLogger()


def search_api_error_handling(method):
"""
Decorator (similar to `queries_records`) to handle exceptions and present in a way
required for the search API. The decorator should be applied to search API endpoint
resources
:param method: The method for the endpoint
:raises: Any exception caught by the execution of `method`
"""

@wraps(method)
def wrapper_error_handling(*args, **kwargs):
try:
return method(*args, **kwargs)
except (ValueError, TypeError, AttributeError) as e:
log.exception(msg=e.args)
raise BadRequestError(create_error_message(BadRequestError()))
except Exception as e:
log.exception(msg=e.args)
try:
e.status_code
except AttributeError:
# If no status code exists (for non-API defined exceptions), defensively
# assign a 500
e.status_code = 500

raise type(e)(create_error_message(e))

def create_error_message(e):
return {
"error": {
"statusCode": e.status_code,
"name": e.__class__.__name__,
"message": str(e),
},
}

return wrapper_error_handling


@client_manager
def get_search(entity_name, filters):
"""
Expand Down

0 comments on commit 3a5a3e8

Please sign in to comment.