Skip to content

Commit 4e99e26

Browse files
committed
🐛 Update safe_status_message to truncate messages to 50 characters and append ellipsis; enhance tests for truncation behavior
1 parent 963013f commit 4e99e26

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,27 @@ def _pred(obj) -> bool:
130130
return http_statuses
131131

132132

133-
def safe_status_message(message: str | None, max_length: int = 1500) -> str | None:
133+
def safe_status_message(message: str | None, max_length: int = 50) -> str | None:
134134
"""
135135
Truncates a status-message (i.e. `reason` in HTTP errors) to a maximum length, replacing newlines with spaces.
136136
137+
If the message is longer than max_length, it will be truncated and "..." will be appended.
138+
137139
This prevents issues such as:
138140
- `aiohttp.http_exceptions.LineTooLong`: 400, message: Got more than 8190 bytes when reading Status line is too long.
139141
- Multiline not allowed in HTTP reason attribute (aiohttp now raises ValueError).
140142
141143
See:
144+
- When to use http status and/or text messages https://github.com/ITISFoundation/osparc-simcore/pull/7760
142145
- [RFC 9112, Section 4.1: HTTP/1.1 Message Syntax and Routing](https://datatracker.ietf.org/doc/html/rfc9112#section-4.1) (status line length limits)
143146
- [RFC 9110, Section 15.5: Reason Phrase](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5) (reason phrase definition)
144147
"""
145-
return message.replace("\n", " ")[:max_length] if message else None
148+
if not message:
149+
return None
150+
151+
flat_message = message.replace("\n", " ")
152+
if len(flat_message) <= max_length:
153+
return flat_message
154+
155+
# Truncate and add ellipsis
156+
return flat_message[: max_length - 3] + "..."

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ def tests_exception_to_response(skip_details: bool, error_code: ErrorCodeStr | N
109109
"Message\nwith\nnewlines",
110110
"Message with newlines",
111111
), # Newlines are replaced with spaces
112-
("A" * 2000, "A" * 1500), # Long message gets truncated to max_length (1500)
112+
("A" * 100, "A" * 47 + "..."), # Long message gets truncated with ellipsis
113113
(
114-
"Line1\nLine2\nLine3" + "X" * 1500,
115-
"Line1 Line2 Line3" + "X" * 1483,
116-
), # Combined case: newlines and truncation
114+
"Line1\nLine2\nLine3" + "X" * 100,
115+
"Line1 Line2 Line3" + "X" * 30 + "...",
116+
), # Combined case: newlines and truncation with ellipsis
117117
],
118118
ids=[
119119
"none_input",
@@ -137,6 +137,9 @@ def test_safe_status_message(input_message: str | None, expected_output: str | N
137137
# Check length constraint is respected
138138
if result_custom is not None:
139139
assert len(result_custom) <= custom_max
140+
# Check that ellipsis is added when truncated
141+
if input_message and len(input_message.replace("\n", " ")) > custom_max:
142+
assert result_custom.endswith("...")
140143

141144
# Verify it can be used in a web response without raising exceptions
142145
try:

0 commit comments

Comments
 (0)