Skip to content

Commit e04da11

Browse files
Copy unsafe setting from session cookie jar to ad-hoc request cookie jar (aio-libs#12271)
1 parent a6687c2 commit e04da11

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
@@ -153,6 +153,11 @@ async def close(self) -> None:
153153
class AbstractCookieJar(Sized, Iterable[Morsel[str]]):
154154
"""Abstract Cookie Jar."""
155155

156+
@property
157+
@abstractmethod
158+
def unsafe(self) -> bool:
159+
"""Return True if cookies can be used with IP addresses."""
160+
156161
@property
157162
@abstractmethod
158163
def quote_cookie(self) -> bool:

aiohttp/client.py

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

671671
if cookies is not None:
672672
tmp_cookie_jar = CookieJar(
673-
quote_cookie=self._cookie_jar.quote_cookie
673+
unsafe=self._cookie_jar.unsafe,
674+
quote_cookie=self._cookie_jar.quote_cookie,
674675
)
675676
tmp_cookie_jar.update_cookies(cookies)
676677
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
@@ -106,6 +106,10 @@ def __init__(
106106
self._expire_heap: list[tuple[float, tuple[str, str, str]]] = []
107107
self._expirations: dict[tuple[str, str, str], float] = {}
108108

109+
@property
110+
def unsafe(self) -> bool:
111+
return self._unsafe
112+
109113
@property
110114
def quote_cookie(self) -> bool:
111115
return self._quote_cookie
@@ -546,6 +550,10 @@ def __iter__(self) -> "Iterator[Morsel[str]]":
546550
def __len__(self) -> int:
547551
return 0
548552

553+
@property
554+
def unsafe(self) -> bool:
555+
return False
556+
549557
@property
550558
def quote_cookie(self) -> bool:
551559
return True

tests/test_client_session.py

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

778+
@property
779+
def unsafe(self) -> bool:
780+
return False
781+
778782
@property
779783
def quote_cookie(self) -> bool:
780784
return True
@@ -800,6 +804,7 @@ def __iter__(self) -> Iterator[Any]:
800804
jar = MockCookieJar()
801805

802806
assert jar.quote_cookie is True
807+
assert jar.unsafe is False
803808
assert len(jar) == 0
804809
assert list(jar) == []
805810
jar.clear()
@@ -857,6 +862,27 @@ async def handler(_: web.Request) -> web.Response:
857862
assert resp.request_info.headers.get("Cookie", "") == "name=val=foobar"
858863

859864

865+
async def test_cookies_with_unsafe_cookie_jar(
866+
aiohttp_server: AiohttpServer,
867+
) -> None:
868+
async def handler(request: web.Request) -> web.Response:
869+
return web.Response()
870+
871+
app = web.Application()
872+
app.router.add_route("GET", "/", handler)
873+
server = await aiohttp_server(app)
874+
jar = CookieJar(unsafe=True)
875+
# Use an IP-based URL to verify that ad-hoc cookies are sent
876+
# when the session cookie jar has unsafe=True.
877+
ip_url = server.make_url("/")
878+
assert ip_url.host is not None
879+
assert ip_url.host.count(".") == 3 # Sanity check it looks like an IP address
880+
cookies = {"adhoc": "value"}
881+
async with aiohttp.ClientSession(cookie_jar=jar) as sess:
882+
async with sess.request("GET", ip_url, cookies=cookies) as resp:
883+
assert "adhoc=value" in resp.request_info.headers.get("Cookie", "")
884+
885+
860886
async def test_session_default_version(loop: asyncio.AbstractEventLoop) -> None:
861887
session = aiohttp.ClientSession()
862888
assert session.version == aiohttp.HttpVersion11

tests/test_cookiejar.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ async def test_path_filter_diff_folder_same_name_return_best_match_independent_f
761761
async def test_dummy_cookie_jar() -> None:
762762
cookie = SimpleCookie("foo=bar; Domain=example.com;")
763763
dummy_jar = DummyCookieJar()
764+
assert dummy_jar.unsafe is False
764765
assert dummy_jar.quote_cookie is True
765766
assert len(dummy_jar) == 0
766767
dummy_jar.update_cookies(cookie)
@@ -1621,3 +1622,11 @@ def test_save_load_json_secure_cookies(tmp_path: Path) -> None:
16211622
assert cookie["secure"] is True
16221623
assert cookie["httponly"] is True
16231624
assert cookie["domain"] == "example.com"
1625+
1626+
1627+
async def test_cookie_jar_unsafe_property() -> None:
1628+
jar_safe = CookieJar()
1629+
assert jar_safe.unsafe is False
1630+
1631+
jar_unsafe = CookieJar(unsafe=True)
1632+
assert jar_unsafe.unsafe is True

0 commit comments

Comments
 (0)