Skip to content

Commit 4adfd6e

Browse files
committed
refactring
1 parent 5b1b84a commit 4adfd6e

File tree

1 file changed

+105
-75
lines changed

1 file changed

+105
-75
lines changed

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

Lines changed: 105 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -42,36 +42,107 @@ def is_api_request(request: web.Request, api_version: str) -> bool:
4242
return bool(request.path.startswith(base_path))
4343

4444

45-
def error_middleware_factory( # noqa: C901
46-
api_version: str,
47-
) -> Middleware:
48-
_is_prod: bool = is_production_environ()
49-
50-
def _process_and_raise_unexpected_error(request: web.BaseRequest, err: Exception):
51-
error_code = create_error_code(err)
52-
error_context: dict[str, Any] = {
53-
"request.remote": f"{request.remote}",
54-
"request.method": f"{request.method}",
55-
"request.path": f"{request.path}",
56-
}
57-
58-
user_error_msg = _FMSG_INTERNAL_ERROR_USER_FRIENDLY
59-
http_error = create_http_error(
60-
err,
45+
def _process_and_raise_unexpected_error(
46+
request: web.BaseRequest, err: Exception, *, skip_internal_error_details: bool
47+
):
48+
"""Process unexpected exceptions and raise them as HTTP errors with proper formatting."""
49+
error_code = create_error_code(err)
50+
error_context: dict[str, Any] = {
51+
"request.remote": f"{request.remote}",
52+
"request.method": f"{request.method}",
53+
"request.path": f"{request.path}",
54+
}
55+
56+
user_error_msg = _FMSG_INTERNAL_ERROR_USER_FRIENDLY
57+
http_error = create_http_error(
58+
err,
59+
user_error_msg,
60+
web.HTTPInternalServerError,
61+
skip_internal_error_details=skip_internal_error_details,
62+
error_code=error_code,
63+
)
64+
_logger.exception(
65+
**create_troubleshotting_log_kwargs(
6166
user_error_msg,
62-
web.HTTPInternalServerError,
63-
skip_internal_error_details=_is_prod,
67+
error=err,
68+
error_context=error_context,
6469
error_code=error_code,
6570
)
66-
_logger.exception(
67-
**create_troubleshotting_log_kwargs(
68-
user_error_msg,
69-
error=err,
70-
error_context=error_context,
71-
error_code=error_code,
72-
)
71+
)
72+
raise http_error
73+
74+
75+
def _handle_http_error(err: web.HTTPError) -> None:
76+
"""Handle standard HTTP errors by ensuring they're properly formatted."""
77+
err.content_type = MIMETYPE_APPLICATION_JSON
78+
if err.reason:
79+
err.set_status(err.status, safe_status_message(message=err.reason))
80+
81+
if not err.text or not is_enveloped_from_text(err.text):
82+
error_message = err.text or err.reason or "Unexpected error"
83+
error_model = ErrorGet(
84+
errors=[
85+
ErrorItemType.from_error(err),
86+
],
87+
status=err.status,
88+
logs=[
89+
LogMessageType(message=error_message, level="ERROR"),
90+
],
91+
message=error_message,
7392
)
74-
raise http_error
93+
err.text = EnvelopeFactory(error=error_model).as_text()
94+
95+
96+
def _handle_http_successful(
97+
err: web.HTTPSuccessful, request: web.Request, *, skip_internal_error_details: bool
98+
) -> None:
99+
"""Handle successful HTTP responses, ensuring they're properly enveloped."""
100+
err.content_type = MIMETYPE_APPLICATION_JSON
101+
if err.reason:
102+
err.set_status(err.status, safe_status_message(message=err.reason))
103+
104+
if err.text:
105+
try:
106+
payload = json_loads(err.text)
107+
if not is_enveloped_from_map(payload):
108+
payload = wrap_as_envelope(data=payload)
109+
err.text = json_dumps(payload)
110+
except Exception as other_error: # pylint: disable=broad-except
111+
_process_and_raise_unexpected_error(
112+
request,
113+
other_error,
114+
skip_internal_error_details=skip_internal_error_details,
115+
)
116+
117+
118+
def _handle_not_implemented(
119+
err: NotImplementedError, *, skip_internal_error_details: bool
120+
) -> None:
121+
"""Handle NotImplementedError by converting to appropriate HTTP error."""
122+
http_error = create_http_error(
123+
err,
124+
f"{err}",
125+
web.HTTPNotImplemented,
126+
skip_internal_error_details=skip_internal_error_details,
127+
)
128+
raise http_error from err
129+
130+
131+
def _handle_timeout(err: TimeoutError, *, skip_internal_error_details: bool) -> None:
132+
"""Handle TimeoutError by converting to appropriate HTTP error."""
133+
http_error = create_http_error(
134+
err,
135+
f"{err}",
136+
web.HTTPGatewayTimeout,
137+
skip_internal_error_details=skip_internal_error_details,
138+
)
139+
raise http_error from err
140+
141+
142+
def error_middleware_factory( # noqa: C901
143+
api_version: str,
144+
) -> Middleware:
145+
_is_prod: bool = is_production_environ()
75146

76147
@web.middleware
77148
async def _middleware_handler(request: web.Request, handler: Handler): # noqa: C901
@@ -86,71 +157,30 @@ async def _middleware_handler(request: web.Request, handler: Handler): # noqa:
86157
return await handler(request)
87158

88159
except web.HTTPError as err:
89-
90-
err.content_type = MIMETYPE_APPLICATION_JSON
91-
if err.reason:
92-
err.set_status(err.status, safe_status_message(message=err.reason))
93-
94-
if not err.text or not is_enveloped_from_text(err.text):
95-
error_message = err.text or err.reason or "Unexpected error"
96-
error_model = ErrorGet(
97-
errors=[
98-
ErrorItemType.from_error(err),
99-
],
100-
status=err.status,
101-
logs=[
102-
LogMessageType(message=error_message, level="ERROR"),
103-
],
104-
message=error_message,
105-
)
106-
err.text = EnvelopeFactory(error=error_model).as_text()
107-
160+
_handle_http_error(err)
108161
raise
109162

110163
except web.HTTPSuccessful as err:
111-
err.content_type = MIMETYPE_APPLICATION_JSON
112-
if err.reason:
113-
err.set_status(err.status, safe_status_message(message=err.reason))
114-
115-
if err.text:
116-
try:
117-
payload = json_loads(err.text)
118-
if not is_enveloped_from_map(payload):
119-
payload = wrap_as_envelope(data=payload)
120-
err.text = json_dumps(payload)
121-
except Exception as other_error: # pylint: disable=broad-except
122-
_process_and_raise_unexpected_error(request, other_error)
164+
_handle_http_successful(err, request, skip_internal_error_details=_is_prod)
123165
raise
124166

125167
except web.HTTPRedirection as err:
126168
_logger.debug("Redirected to %s", err)
127169
raise
128170

129171
except NotImplementedError as err:
130-
http_error = create_http_error(
131-
err,
132-
f"{err}",
133-
web.HTTPNotImplemented,
134-
skip_internal_error_details=_is_prod,
135-
)
136-
raise http_error from err
172+
_handle_not_implemented(err, skip_internal_error_details=_is_prod)
137173

138174
except TimeoutError as err:
139-
http_error = create_http_error(
140-
err,
141-
f"{err}",
142-
web.HTTPGatewayTimeout,
143-
skip_internal_error_details=_is_prod,
144-
)
145-
raise http_error from err
175+
_handle_timeout(err, skip_internal_error_details=_is_prod)
146176

147177
except Exception as err: # pylint: disable=broad-except
148-
_process_and_raise_unexpected_error(request, err)
178+
_process_and_raise_unexpected_error(
179+
request, err, skip_internal_error_details=_is_prod
180+
)
149181

150182
# adds identifier (mostly for debugging)
151-
setattr( # noqa: B010
152-
_middleware_handler, "__middleware_name__", f"{__name__}.error_{api_version}"
153-
)
183+
_middleware_handler.__middleware_name__ = f"{__name__}.error_{api_version}"
154184

155185
return _middleware_handler
156186

0 commit comments

Comments
 (0)