From 935f22d31d96c6810cf7938815b25c8822d892fb Mon Sep 17 00:00:00 2001 From: Matthew Richards Date: Thu, 24 Feb 2022 14:05:38 +0000 Subject: [PATCH 1/2] fix: improve error handling for search API exceptions #319 --- datagateway_api/src/search_api/helpers.py | 30 ++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/datagateway_api/src/search_api/helpers.py b/datagateway_api/src/search_api/helpers.py index 25e89aa9..e4c125ad 100644 --- a/datagateway_api/src/search_api/helpers.py +++ b/datagateway_api/src/search_api/helpers.py @@ -2,9 +2,12 @@ import json import logging +from pydantic import ValidationError + from datagateway_api.src.common.exceptions import ( BadRequestError, MissingRecordError, + SearchAPIError, ) from datagateway_api.src.common.filter_order_handler import FilterOrderHandler from datagateway_api.src.search_api.filters import ( @@ -36,20 +39,29 @@ def search_api_error_handling(method): def wrapper_error_handling(*args, **kwargs): try: return method(*args, **kwargs) - except (ValueError, TypeError, AttributeError) as e: + except ValidationError as e: + log.exception(msg=e.args) + assign_status_code(e, 500) + raise SearchAPIError(create_error_message(e)) + except (ValueError, TypeError, AttributeError, KeyError) as e: log.exception(msg=e.args) - raise BadRequestError(create_error_message(BadRequestError())) + assign_status_code(e, 400) + raise BadRequestError(create_error_message(e)) 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 - + # Defensively assign a 500 if the exception doesn't already have a status + # code + assign_status_code(e, 500) raise type(e)(create_error_message(e)) + def assign_status_code(e, status_code): + try: + # If no status code exists (for non-API defined exceptions), assign a status + # code + e.status_code + except AttributeError: + e.status_code = status_code + def create_error_message(e): return { "error": { From 1e4298107c489f3927fd3b7b31cdaf10e37db0f4 Mon Sep 17 00:00:00 2001 From: Matthew Richards Date: Fri, 25 Feb 2022 10:56:48 +0000 Subject: [PATCH 2/2] test: improve code coverage for search API error formatting #319 --- test/search_api/test_error_handling.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/search_api/test_error_handling.py b/test/search_api/test_error_handling.py index 619129da..aece71e1 100644 --- a/test/search_api/test_error_handling.py +++ b/test/search_api/test_error_handling.py @@ -8,6 +8,7 @@ SearchAPIError, ) from datagateway_api.src.search_api.helpers import search_api_error_handling +from datagateway_api.src.search_api.models import Document class TestErrorHandling: @@ -24,6 +25,7 @@ class TestErrorHandling: pytest.param(ValueError, BadRequestError, 400, id="Value error"), pytest.param(AttributeError, BadRequestError, 400, id="Attribute error"), pytest.param(ImportError, ImportError, 500, id="Import error"), + pytest.param(Document, SearchAPIError, 500, id="Validation error"), ], ) def test_valid_error_raised( @@ -31,7 +33,11 @@ def test_valid_error_raised( ): @search_api_error_handling def raise_exception(): - raise raised_exception() + if isinstance(raised_exception(), Exception): + raise raised_exception() + else: + # To raise Pydantic ValidationError from object creation + raised_exception() try: raise_exception()