Skip to content

Commit f6f8f0a

Browse files
committed
json-error
1 parent da3be32 commit f6f8f0a

File tree

3 files changed

+47
-14
lines changed

3 files changed

+47
-14
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from typing import Annotated
2+
3+
from pydantic import BaseModel, ConfigDict, Field
4+
5+
from .basic_types import IDStr
6+
7+
8+
class ErrorGet(BaseModel):
9+
msg: Annotated[
10+
str, Field(min_length=5, description="Message displayed to the user")
11+
]
12+
support_id: Annotated[
13+
IDStr | None,
14+
Field(description="ID to track the incident during support", alias="supportId"),
15+
] = None
16+
17+
model_config = ConfigDict(
18+
populate_by_name=True,
19+
extra="ignore", # Used to prune extra fields from internal data
20+
frozen=True,
21+
json_schema_extra={
22+
"examples": [
23+
{"msg": "Sorry you do not have sufficient access rights for product"},
24+
{
25+
"msg": "Opps this error was unexpected. We are working on that!",
26+
"supportId": "OEC:12346789",
27+
},
28+
]
29+
},
30+
)

services/web/server/src/simcore_service_webserver/exceptions_handlers_http_error_map.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
from typing import NamedTuple, TypeAlias
44

55
from aiohttp import web
6+
from common_library.error_codes import create_error_code
7+
from common_library.json_serialization import json_dumps
8+
from models_library.basic_types import IDStr
9+
from models_library.rest_error import ErrorGet
610
from servicelib.aiohttp.web_exceptions_extension import get_all_aiohttp_http_exceptions
711
from servicelib.logging_errors import create_troubleshotting_log_kwargs
812
from servicelib.status_codes_utils import is_5xx_server_error
@@ -68,11 +72,15 @@ async def _exception_handler(
6872
_DefaultDict(getattr(exception, "__dict__", {}))
6973
)
7074

75+
error = ErrorGet(msg=user_msg)
76+
7177
if is_5xx_server_error(status_code):
78+
oec = create_error_code(exception)
7279
_logger.exception(
7380
**create_troubleshotting_log_kwargs(
7481
user_msg,
7582
error=exception,
83+
error_code=oec,
7684
error_context={
7785
"request": request,
7886
"request.remote": f"{request.remote}",
@@ -81,16 +89,11 @@ async def _exception_handler(
8189
},
8290
)
8391
)
92+
error = ErrorGet(msg=user_msg, support_id=IDStr(oec))
8493

85-
# TODO: make this part customizable? e.g. so we can inject e.g. oec?
86-
# TODO: connect with ErrorModel
8794
return web.json_response(
88-
{
89-
"error": {
90-
"msg": user_msg,
91-
}
92-
},
93-
status=status_code,
95+
data={"error": error.model_dump(exclude_unset=True, mode="json")},
96+
dumps=json_dumps,
9497
)
9598

9699
return _exception_handler

services/web/server/tests/unit/isolated/test_exceptions_handlers.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from aiohttp import web
1313
from aiohttp.test_utils import make_mocked_request
1414
from servicelib.aiohttp import status
15+
from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON
1516
from simcore_service_webserver.errors import WebServerBaseError
1617
from simcore_service_webserver.exceptions_handlers import (
1718
ExceptionToHttpErrorMap,
@@ -94,7 +95,8 @@ async def test_factory__create_exception_handler_from_http_error(
9495
response = await one_error_to_404(fake_request, caught)
9596
assert response.status == status.HTTP_404_NOT_FOUND
9697
assert response.text is not None
97-
assert "one error message" in response.text
98+
assert "one error message" in response.reason
99+
assert response.content_type == MIMETYPE_APPLICATION_JSON
98100

99101

100102
async def test_factory__create_exception_handler_from_http_error_map(
@@ -111,12 +113,10 @@ async def test_factory__create_exception_handler_from_http_error_map(
111113
)
112114

113115
# Converts exception in map
114-
with pytest.raises(web.HTTPBadRequest) as exc_info:
115-
await exc_handler(fake_request, OneError())
116116

117-
got_exc = exc_info.value
118-
assert isinstance(got_exc, web.HTTPBadRequest)
119-
assert got_exc.reason == "Error One mapped to 400"
117+
response = await exc_handler(fake_request, OneError())
118+
assert response.status == status.HTTP_400_BAD_REQUEST
119+
assert response.reason == "Error One mapped to 400"
120120

121121
# By-passes exceptions not listed
122122
err = RuntimeError()

0 commit comments

Comments
 (0)