diff --git a/packages/service-library/src/servicelib/aiohttp/rest_models.py b/packages/service-library/src/servicelib/aiohttp/rest_models.py index f35cabe4394..36902f17b77 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_models.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_models.py @@ -27,4 +27,4 @@ class ErrorType: logs: list[LogMessageType] = field(default_factory=list) errors: list[ErrorItemType] = field(default_factory=list) status: int = 400 - message: str = "Unexpected client error" + message: str = "Unexpected error" diff --git a/packages/service-library/src/servicelib/aiohttp/rest_responses.py b/packages/service-library/src/servicelib/aiohttp/rest_responses.py index 150265b6f42..569ab56fbca 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_responses.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_responses.py @@ -13,6 +13,7 @@ from servicelib.aiohttp.status import HTTP_200_OK from ..mimetype_constants import MIMETYPE_APPLICATION_JSON +from ..status_utils import get_code_description from .rest_models import ErrorItemType, ErrorType _ENVELOPE_KEYS = ("data", "error") @@ -96,16 +97,20 @@ def create_http_error( # TODO: guarantee no throw! is_internal_error: bool = http_error_cls == web.HTTPInternalServerError + default_message = reason or get_code_description(http_error_cls.status_code) if is_internal_error and skip_internal_error_details: error = ErrorType( errors=[], status=http_error_cls.status_code, + message=default_message, ) else: + items = [ErrorItemType.from_error(err) for err in errors] error = ErrorType( - errors=[ErrorItemType.from_error(err) for err in errors], + errors=items, status=http_error_cls.status_code, + message=items[0].message if items else default_message, ) assert not http_error_cls.empty_body # nosec diff --git a/packages/service-library/tests/aiohttp/test_rest_responses.py b/packages/service-library/tests/aiohttp/test_rest_responses.py index ce47777cd4f..7077a93cb0f 100644 --- a/packages/service-library/tests/aiohttp/test_rest_responses.py +++ b/packages/service-library/tests/aiohttp/test_rest_responses.py @@ -5,6 +5,7 @@ import itertools import pytest +from aiohttp import web from aiohttp.web_exceptions import ( HTTPBadRequest, HTTPError, @@ -14,10 +15,14 @@ HTTPNotModified, HTTPOk, ) +from servicelib.aiohttp import status from servicelib.aiohttp.rest_responses import ( _STATUS_CODE_TO_HTTP_ERRORS, + create_http_error, + exception_to_response, get_http_error, ) +from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON # @@ -53,3 +58,29 @@ def test_collected_http_errors_map(status_code: int, http_error_cls: type[HTTPEr assert http_error_cls != HTTPError assert issubclass(http_error_cls, HTTPError) + + +@pytest.mark.parametrize("skip_details", [True, False]) +def tests_exception_to_response(skip_details: bool): + exception = create_http_error( + errors=[RuntimeError("foo")], + reason="Something whent wrong", + http_error_cls=web.HTTPInternalServerError, + skip_internal_error_details=skip_details, + ) + + # For now until deprecated SEE https://github.com/aio-libs/aiohttp/issues/2415 + assert isinstance(exception, Exception) + assert isinstance(exception, web.Response) + assert hasattr(exception, "__http_exception__") + + # until they have exception.make_response(), we user + response = exception_to_response(exception) + assert isinstance(response, web.Response) + assert not isinstance(response, Exception) + assert not hasattr(response, "__http_exception__") + + assert response.content_type == MIMETYPE_APPLICATION_JSON + assert response.status == status.HTTP_500_INTERNAL_SERVER_ERROR + assert response.text + assert response.body