Skip to content

Commit 6a86e0f

Browse files
[PR aio-libs#12271/e04da11f backport][3.14] Copy unsafe setting from session cookie jar to ad-hoc request cookie jar (aio-libs#12274)
**This is a backport of PR aio-libs#12271 as merged into master (e04da11).** Co-authored-by: Krishna Chaitanya <krishnabkc15@gmail.com>
1 parent f983c51 commit 6a86e0f

6 files changed

Lines changed: 51 additions & 1 deletion

File tree

CHANGES/12011.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed ad-hoc cookies passed to individual requests not being sent when the session's cookie jar has ``unsafe=True`` and the target URL uses an IP address, by copying the ``unsafe`` setting from the session's cookie jar to the temporary cookie jar -- by :user:`Krishnachaitanyakc`.

aiohttp/abc.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ class AbstractCookieJar(Sized, IterableBase):
163163
def __init__(self, *, loop: asyncio.AbstractEventLoop | None = None) -> None:
164164
self._loop = loop or asyncio.get_running_loop()
165165

166+
@property
167+
@abstractmethod
168+
def unsafe(self) -> bool:
169+
"""Return True if cookies can be used with IP addresses."""
170+
166171
@property
167172
@abstractmethod
168173
def quote_cookie(self) -> bool:

aiohttp/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,8 @@ async def _request(
724724

725725
if cookies is not None:
726726
tmp_cookie_jar = CookieJar(
727-
quote_cookie=self._cookie_jar.quote_cookie
727+
unsafe=self._cookie_jar.unsafe,
728+
quote_cookie=self._cookie_jar.quote_cookie,
728729
)
729730
tmp_cookie_jar.update_cookies(cookies)
730731
req_cookies = tmp_cookie_jar.filter_cookies(url)

aiohttp/cookiejar.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ def __init__(
143143
self._expire_heap: list[tuple[float, tuple[str, str, str]]] = []
144144
self._expirations: dict[tuple[str, str, str], float] = {}
145145

146+
@property
147+
def unsafe(self) -> bool:
148+
return self._unsafe
149+
146150
@property
147151
def quote_cookie(self) -> bool:
148152
return self._quote_cookie
@@ -600,6 +604,10 @@ def __iter__(self) -> "Iterator[Morsel[str]]":
600604
def __len__(self) -> int:
601605
return 0
602606

607+
@property
608+
def unsafe(self) -> bool:
609+
return False
610+
603611
@property
604612
def quote_cookie(self) -> bool:
605613
return True

tests/test_client_session.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,10 @@ def __init__(self) -> None:
747747
self._clear_domain_mock = mock.Mock()
748748
self._items: list[Any] = []
749749

750+
@property
751+
def unsafe(self) -> bool:
752+
return False
753+
750754
@property
751755
def quote_cookie(self) -> bool:
752756
return True
@@ -772,6 +776,7 @@ def __iter__(self) -> Iterator[Any]:
772776
jar = MockCookieJar()
773777

774778
assert jar.quote_cookie is True
779+
assert jar.unsafe is False
775780
assert len(jar) == 0
776781
assert list(jar) == []
777782
jar.clear()
@@ -828,6 +833,27 @@ async def handler(_: web.Request) -> web.Response:
828833
assert resp.request_info.headers.get("Cookie", "") == "name=val=foobar"
829834

830835

836+
async def test_cookies_with_unsafe_cookie_jar(
837+
aiohttp_server: AiohttpServer,
838+
) -> None:
839+
async def handler(request: web.Request) -> web.Response:
840+
return web.Response()
841+
842+
app = web.Application()
843+
app.router.add_route("GET", "/", handler)
844+
server = await aiohttp_server(app)
845+
jar = CookieJar(unsafe=True)
846+
# Use an IP-based URL to verify that ad-hoc cookies are sent
847+
# when the session cookie jar has unsafe=True.
848+
ip_url = server.make_url("/")
849+
assert ip_url.host is not None
850+
assert ip_url.host.count(".") == 3 # Sanity check it looks like an IP address
851+
cookies = {"adhoc": "value"}
852+
async with aiohttp.ClientSession(cookie_jar=jar) as sess:
853+
async with sess.request("GET", ip_url, cookies=cookies) as resp:
854+
assert "adhoc=value" in resp.request_info.headers.get("Cookie", "")
855+
856+
831857
async def test_session_default_version(loop: asyncio.AbstractEventLoop) -> None:
832858
session = aiohttp.ClientSession()
833859
assert session.version == aiohttp.HttpVersion11

tests/test_cookiejar.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ async def make_jar():
827827
async def test_dummy_cookie_jar() -> None:
828828
cookie = SimpleCookie("foo=bar; Domain=example.com;")
829829
dummy_jar = DummyCookieJar()
830+
assert dummy_jar.unsafe is False
830831
assert dummy_jar.quote_cookie is True
831832
assert len(dummy_jar) == 0
832833
dummy_jar.update_cookies(cookie)
@@ -1809,3 +1810,11 @@ async def test_save_load_json_secure_cookies(tmp_path: Path) -> None:
18091810
assert cookie["secure"] is True
18101811
assert cookie["httponly"] is True
18111812
assert cookie["domain"] == "example.com"
1813+
1814+
1815+
async def test_cookie_jar_unsafe_property() -> None:
1816+
jar_safe = CookieJar()
1817+
assert jar_safe.unsafe is False
1818+
1819+
jar_unsafe = CookieJar(unsafe=True)
1820+
assert jar_unsafe.unsafe is True

0 commit comments

Comments
 (0)