Skip to content

Commit 68679ab

Browse files
authored
♻️🐛 Fix: Prevent aiohttp.http_exceptions.LineTooLong and improve diagnostics (#8174)
1 parent 28845dd commit 68679ab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+130
-135
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def handle_aiohttp_web_http_error(
118118
exception.content_type = MIMETYPE_APPLICATION_JSON
119119
if exception.reason:
120120
exception.set_status(
121-
exception.status, safe_status_message(message=exception.reason)
121+
exception.status, reason=safe_status_message(message=exception.reason)
122122
)
123123

124124
if not exception.text or not is_enveloped_from_text(exception.text):
@@ -165,7 +165,7 @@ def _handle_aiohttp_web_http_successful(
165165
exception.content_type = MIMETYPE_APPLICATION_JSON
166166
if exception.reason:
167167
exception.set_status(
168-
exception.status, safe_status_message(message=exception.reason)
168+
exception.status, reason=safe_status_message(message=exception.reason)
169169
)
170170

171171
if exception.text and not is_enveloped_from_text(exception.text):

services/web/server/src/simcore_service_webserver/api_keys/_service.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ async def get_api_key(
7777
if api_key is not None:
7878
return api_key
7979

80-
raise ApiKeyNotFoundError(api_key_id=api_key_id)
80+
raise ApiKeyNotFoundError(
81+
api_key_id=api_key_id, product_name=product_name, user_id=user_id
82+
)
8183

8284

8385
async def list_api_keys(
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from ..errors import WebServerBaseError
22

33

4-
class ApiKeysValueError(WebServerBaseError, ValueError):
5-
...
4+
class ApiKeysValueError(WebServerBaseError, ValueError): ...
65

76

87
class ApiKeyDuplicatedDisplayNameError(ApiKeysValueError):
9-
msg_template = "API Key with display name '{display_name}' already exists. {reason}"
8+
msg_template = (
9+
"API Key with display name '{display_name}' already exists: {details}"
10+
)
1011

1112

1213
class ApiKeyNotFoundError(ApiKeysValueError):
13-
msg_template = "API Key with ID '{api_key_id}' not found. {reason}"
14+
msg_template = "API Key with ID '{api_key_id}' not found: {details}"

services/web/server/src/simcore_service_webserver/director_v2/_client_base.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import aiohttp
55
from aiohttp import ClientSession, ClientTimeout, web
66
from servicelib.aiohttp import status
7+
from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON
78
from tenacity import retry
89
from tenacity.before_sleep import before_sleep_log
910
from tenacity.stop import stop_after_attempt
@@ -36,13 +37,14 @@
3637

3738

3839
def _get_exception_from(
39-
status_code: int, on_error: _StatusToExceptionMapping | None, reason: str, url: URL
40+
status_code: int, on_error: _StatusToExceptionMapping | None, details: str, url: URL
4041
):
4142
if on_error and status_code in on_error:
42-
exc, exc_ctx = on_error[status_code]
43-
return exc(**exc_ctx, status=status_code, reason=reason)
43+
exc_cls, exc_ctx = on_error[status_code]
44+
return exc_cls(**exc_ctx, status=status_code, details=details)
45+
4446
# default
45-
return DirectorV2ServiceError(status=status_code, reason=reason, url=url)
47+
return DirectorV2ServiceError(status=status_code, details=details, url=url)
4648

4749

4850
@retry(**DEFAULT_RETRY_POLICY)
@@ -61,13 +63,13 @@ async def _make_request(
6163
) as response:
6264
payload: dict[str, Any] | list[dict[str, Any]] | None | str = (
6365
await response.json()
64-
if response.content_type == "application/json"
66+
if response.content_type == MIMETYPE_APPLICATION_JSON
6567
else await response.text()
6668
)
6769

6870
if response.status != expected_status.status_code:
6971
raise _get_exception_from(
70-
response.status, on_error, reason=f"{payload}", url=url
72+
response.status, on_error, details=f"{payload}", url=url
7173
)
7274
return payload
7375

@@ -99,13 +101,13 @@ async def request_director_v2(
99101
except TimeoutError as err:
100102
raise DirectorV2ServiceError(
101103
status=status.HTTP_503_SERVICE_UNAVAILABLE,
102-
reason=f"request to director-v2 timed-out: {err}",
104+
details=f"request to director-v2 timed-out: {err}",
103105
url=url,
104106
) from err
105107

106108
except aiohttp.ClientError as err:
107109
raise DirectorV2ServiceError(
108110
status=status.HTTP_503_SERVICE_UNAVAILABLE,
109-
reason=f"request to director-v2 service unexpected error {err}",
111+
details=f"request to director-v2 service unexpected error {err}",
110112
url=url,
111113
) from err

services/web/server/src/simcore_service_webserver/director_v2/_controller/_rest_exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def _handler_director_service_error_as_503_or_4xx(
9595
WalletNotEnoughCreditsError: HttpErrorInfo(
9696
status.HTTP_402_PAYMENT_REQUIRED,
9797
user_message(
98-
"Your wallet does not have sufficient credits to run this computation. {reason}",
98+
"Your wallet does not have sufficient credits to run this computation: {details}",
9999
_version=1,
100100
),
101101
),

services/web/server/src/simcore_service_webserver/director_v2/_controller/rest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def start_computation(request: web.Request) -> web.Response:
9595
now = datetime.now(UTC)
9696
if now - created_at > timedelta(minutes=5):
9797
raise web.HTTPBadRequest(
98-
reason=(
98+
text=(
9999
"This client generated collection is not new, "
100100
"it was created more than 5 minutes ago. "
101101
"Therefore, the client is probably wrongly generating it."

services/web/server/src/simcore_service_webserver/director_v2/exceptions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
class DirectorV2ServiceError(WebServerBaseError, RuntimeError):
99
"""Basic exception for errors raised by director-v2"""
1010

11-
msg_template = "Unexpected error: director-v2 returned '{status}', reason '{reason}' after calling '{url}'"
11+
msg_template = "Unexpected error: director-v2 returned '{status}', details '{details}' after calling '{url}'"
1212

13-
def __init__(self, *, status: int, reason: str, **ctx: Any) -> None:
13+
def __init__(self, *, status: int, details: str, **ctx: Any) -> None:
1414
super().__init__(**ctx)
1515
self.status = status
16-
self.reason = reason
16+
self.details = details
1717

1818

1919
class ComputationNotFoundError(DirectorV2ServiceError):

services/web/server/src/simcore_service_webserver/exception_handling/_factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def create_http_error_exception_handlers_map() -> ExceptionHandlersMap:
145145
"""
146146
exc_handlers_map: ExceptionHandlersMap = {
147147
exc_type: create_exception_handler_from_http_info(
148-
status_code=code, msg_template="{reason}"
148+
status_code=code, msg_template="{text}"
149149
)
150150
for code, exc_type in _STATUS_CODE_TO_HTTP_ERRORS.items()
151151
}

services/web/server/src/simcore_service_webserver/folders/_common/exceptions_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@
5656
),
5757
FolderValueNotPermittedError: HttpErrorInfo(
5858
status.HTTP_409_CONFLICT,
59-
user_message("The folder operation cannot be completed: {reason}", _version=1),
59+
user_message("The folder operation cannot be completed: {details}", _version=1),
6060
),
6161
FoldersValueError: HttpErrorInfo(
6262
status.HTTP_409_CONFLICT,
63-
user_message("The folder configuration is invalid: {reason}", _version=1),
63+
user_message("The folder configuration is invalid: {details}", _version=1),
6464
),
6565
ProjectInvalidRightsError: HttpErrorInfo(
6666
status.HTTP_403_FORBIDDEN,

services/web/server/src/simcore_service_webserver/folders/_folders_repository.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ async def get(
338338
row = result.first()
339339
if row is None:
340340
raise FolderAccessForbiddenError(
341-
reason=f"Folder {folder_id} does not exist.",
341+
details=f"Folder {folder_id} does not exist.",
342342
)
343343
return FolderDB.model_validate(row)
344344

@@ -369,7 +369,7 @@ async def get_for_user_or_workspace(
369369
row = await result.first()
370370
if row is None:
371371
raise FolderAccessForbiddenError(
372-
reason=f"User does not have access to the folder {folder_id}. Or folder does not exist.",
372+
details=f"User does not have access to the folder {folder_id}. Or folder does not exist.",
373373
)
374374
return FolderDB.model_validate(row)
375375

@@ -421,7 +421,7 @@ async def update(
421421
result = await conn.stream(query)
422422
row = await result.first()
423423
if row is None:
424-
raise FolderNotFoundError(reason=f"Folder {folders_id_or_ids} not found.")
424+
raise FolderNotFoundError(details=f"Folder {folders_id_or_ids} not found.")
425425
return FolderDB.model_validate(row)
426426

427427

0 commit comments

Comments
 (0)