Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/2928.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed ``Response.text`` raising ``AttributeError`` when ``Response.body`` was set to a string -- by :user:`dhruvildarji`.
6 changes: 6 additions & 0 deletions aiohttp/web_response.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created a StringPayload wrapper that didn't always have a compatible decode method.

Under what condition does it not have a compatible decode() method? It looks like it should work to me...

Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,12 @@ def body(self, body: Any) -> None:
self._body = None
elif isinstance(body, (bytes, bytearray)):
self._body = body
elif isinstance(body, str):
self._body = body.encode(self.charset or "utf-8")
if self.content_type == "application/octet-stream":
self.content_type = "text/plain"
if self.charset is None:
self.charset = "utf-8"
else:
try:
self._body = body = payload.PAYLOAD_REGISTRY.get(body)
Expand Down
42 changes: 42 additions & 0 deletions tests/test_web_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,48 @@ def test_payload_body_get_text(payload: object, expected: str | None) -> None:
assert resp.text == expected


def test_body_setter_with_str_stores_bytes() -> None:
"""Setting body to a str should encode it to bytes (issue #2928)."""
resp = web.Response()
resp.body = "hello"
assert resp.body == b"hello"
assert isinstance(resp.body, bytes)
assert resp.text == "hello"


def test_body_setter_with_str_sets_content_type() -> None:
"""Setting body to a str should set content_type to text/plain."""
resp = web.Response()
resp.body = "hello"
assert resp.content_type == "text/plain"
assert resp.charset == "utf-8"


def test_body_setter_with_str_preserves_existing_content_type() -> None:
"""Setting body to str should not override an existing non-default content_type."""
resp = web.Response(content_type="text/html")
resp.body = "hello"
assert resp.content_type == "text/html"


def test_body_setter_with_str_uses_existing_charset() -> None:
"""Setting body to str should use existing charset for encoding."""
resp = web.Response(charset="latin-1", content_type="text/plain")
resp.body = "caf\u00e9"
assert resp.body == "caf\u00e9".encode("latin-1")
assert resp.text == "caf\u00e9"


def test_body_setter_str_then_text_roundtrip() -> None:
"""body = str -> text -> body roundtrip should be consistent."""
resp = web.Response()
resp.body = "test string"
text = resp.text
assert text == "test string"
resp.text = text
assert resp.body == b"test string"


def test_response_set_content_length() -> None:
resp = web.Response()
with pytest.raises(RuntimeError):
Expand Down
Loading