Skip to content

Commit be15472

Browse files
authored
[PR #10672/35c979b backport][3.11] Fix headers being mutated if passed to web.Response as a CIMultiDict (#10673)
If `CIMultiDict` is passed in we need to make a copy to avoid mutating it. In some cases we used to copy these twice which was fixed in #10045 but for this case that was the only copy being made and the source of this regression. fixes #10670 (cherry picked from commit 35c979b)
1 parent b65000d commit be15472

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

CHANGES/10672.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed :class:`multidict.CIMultiDict` being mutated when passed to :class:`aiohttp.web.Response` -- by :user:`bdraco`.

aiohttp/web_response.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,10 +629,8 @@ def __init__(
629629

630630
if headers is None:
631631
real_headers: CIMultiDict[str] = CIMultiDict()
632-
elif not isinstance(headers, CIMultiDict):
633-
real_headers = CIMultiDict(headers)
634632
else:
635-
real_headers = headers # = cast('CIMultiDict[str]', headers)
633+
real_headers = CIMultiDict(headers)
636634

637635
if content_type is not None and "charset" in content_type:
638636
raise ValueError("charset must not be in content_type argument")

tests/test_web_response.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import aiosignal
1212
import pytest
13-
from multidict import CIMultiDict, CIMultiDictProxy
13+
from multidict import CIMultiDict, CIMultiDictProxy, MultiDict
1414
from re_assert import Matches
1515

1616
from aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs
@@ -1479,3 +1479,15 @@ def test_text_is_json_encoded(self) -> None:
14791479
def test_content_type_is_overrideable(self) -> None:
14801480
resp = json_response({"foo": 42}, content_type="application/vnd.json+api")
14811481
assert "application/vnd.json+api" == resp.content_type
1482+
1483+
1484+
@pytest.mark.parametrize("loose_header_type", (MultiDict, CIMultiDict, dict))
1485+
async def test_passing_cimultidict_to_web_response_not_mutated(
1486+
loose_header_type: type,
1487+
) -> None:
1488+
req = make_request("GET", "/")
1489+
headers = loose_header_type({})
1490+
resp = Response(body=b"answer", headers=headers)
1491+
await resp.prepare(req)
1492+
assert resp.content_length == 6
1493+
assert not headers

0 commit comments

Comments
 (0)