Skip to content

Commit 26838df

Browse files
committed
🐛 Fix: assert request in successful HTTP response handlers and update type hint for create_http_error
1 parent 575a2a3 commit 26838df

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

packages/service-library/src/servicelib/aiohttp/rest_middlewares.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ def _handle_unexpected_exception_as_500(
5151
*,
5252
skip_internal_error_details: bool,
5353
) -> web.HTTPInternalServerError:
54-
"""Process unexpected exceptions and return them as HTTP errors with proper formatting."""
54+
"""Process unexpected exceptions and return them as HTTP errors with proper formatting.
55+
56+
IMPORTANT: this function cannot throw exceptions, as it is called
57+
"""
5558
error_code = create_error_code(exception)
5659
error_context: dict[str, Any] = {
5760
"request.remote": f"{request.remote}",
@@ -60,13 +63,17 @@ def _handle_unexpected_exception_as_500(
6063
}
6164

6265
user_error_msg = _FMSG_INTERNAL_ERROR_USER_FRIENDLY
66+
6367
http_error = create_http_error(
6468
exception,
6569
user_error_msg,
6670
web.HTTPInternalServerError,
6771
skip_internal_error_details=skip_internal_error_details,
6872
error_code=error_code,
6973
)
74+
75+
error_context["http_error"] = http_error
76+
7077
_logger.exception(
7178
**create_troubleshotting_log_kwargs(
7279
user_error_msg,
@@ -177,7 +184,6 @@ async def _middleware_handler(request: web.Request, handler: Handler):
177184
result = _handle_http_successful(request, exc)
178185

179186
except web.HTTPRedirection as exc: # 3XX raised as exceptions
180-
_logger.debug("Redirected to %s", exc)
181187
result = exc
182188

183189
except NotImplementedError as exc:

packages/service-library/tests/aiohttp/test_rest_middlewares.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from aiohttp import web
1515
from aiohttp.test_utils import TestClient
1616
from common_library.json_serialization import json_dumps
17+
from pytest_mock import MockerFixture
1718
from servicelib.aiohttp import status
1819
from servicelib.aiohttp.rest_middlewares import (
1920
envelope_middleware_factory,
@@ -339,3 +340,41 @@ async def test_http_ok_with_text_is_enveloped(client: TestClient):
339340
assert not error
340341
assert data
341342
assert data.get("ok") is True
343+
344+
345+
async def test_exception_in_handler_returns_500(
346+
client: TestClient, mocker: MockerFixture
347+
):
348+
"""Test that exceptions in the handler functions are caught and return 500."""
349+
350+
# Mock _handle_http_successful to raise an exception
351+
def mocked_handler(*args, **kwargs):
352+
msg = "Simulated error in handler"
353+
raise ValueError(msg)
354+
355+
mocker.patch(
356+
"servicelib.aiohttp.rest_middlewares._handle_http_successful",
357+
side_effect=mocked_handler,
358+
)
359+
360+
# Trigger a successful HTTP response that will be processed by our mocked handler
361+
response = await client.get(
362+
"/v1/raise_exception", params={"exc": web.HTTPOk.__name__}
363+
)
364+
365+
# Should return 500 since our handler raised an exception
366+
assert response.status == status.HTTP_500_INTERNAL_SERVER_ERROR
367+
368+
# Check that the response is properly enveloped
369+
payload = await response.json()
370+
assert is_enveloped(payload)
371+
372+
# Verify error details
373+
data, error = unwrap_envelope(payload)
374+
assert not data
375+
assert error
376+
assert error.get("status") == status.HTTP_500_INTERNAL_SERVER_ERROR
377+
378+
# Make sure there are no detailed error logs in production mode
379+
assert not error.get("errors")
380+
assert not error.get("logs")

0 commit comments

Comments
 (0)