Skip to content

Commit 916b3ee

Browse files
brataoBruno Cabralpre-commit-ci[bot]Dreamsorcerer
authored
Fix cookie handling (#6638)
* Fix cookie handling * Fix cookie handling * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update aiohttp/cookiejar.py Co-authored-by: Sam Bull <aa6bs0@sambull.org> Co-authored-by: Bruno Cabral <bruno@potelo.com.br> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sam Bull <aa6bs0@sambull.org>
1 parent 7514f22 commit 916b3ee

File tree

4 files changed

+42
-14
lines changed

4 files changed

+42
-14
lines changed

CHANGES/6638.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Do not overwrite cookies with same name and domain when the path is different.

CONTRIBUTORS.txt

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Brian Bouterse
6363
Brian C. Lane
6464
Brian Muller
6565
Bruce Merry
66+
Bruno Souza Cabral
6667
Bryan Kok
6768
Bryce Drennan
6869
Carl George

aiohttp/cookiejar.py

+18-14
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ def __init__(
6565
treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None
6666
) -> None:
6767
self._loop = asyncio.get_running_loop()
68-
self._cookies: DefaultDict[str, SimpleCookie[str]] = defaultdict(SimpleCookie)
68+
self._cookies: DefaultDict[Tuple[str, str], SimpleCookie[str]] = defaultdict(
69+
SimpleCookie
70+
)
6971
self._host_only_cookies: Set[Tuple[str, str]] = set()
7072
self._unsafe = unsafe
7173
self._quote_cookie = quote_cookie
@@ -82,7 +84,7 @@ def __init__(
8284
]
8385
self._treat_as_secure_origin = treat_as_secure_origin
8486
self._next_expiration = next_whole_second()
85-
self._expirations: Dict[Tuple[str, str], datetime.datetime] = {}
87+
self._expirations: Dict[Tuple[str, str, str], datetime.datetime] = {}
8688
# #4515: datetime.max may not be representable on 32-bit platforms
8789
self._max_time = self.MAX_TIME
8890
try:
@@ -110,20 +112,20 @@ def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:
110112

111113
to_del = []
112114
now = datetime.datetime.now(datetime.timezone.utc)
113-
for domain, cookie in self._cookies.items():
115+
for (domain, path), cookie in self._cookies.items():
114116
for name, morsel in cookie.items():
115-
key = (domain, name)
117+
key = (domain, path, name)
116118
if (
117119
key in self._expirations and self._expirations[key] <= now
118120
) or predicate(morsel):
119121
to_del.append(key)
120122

121-
for domain, name in to_del:
122-
key = (domain, name)
123-
self._host_only_cookies.discard(key)
123+
for domain, path, name in to_del:
124+
self._host_only_cookies.discard((domain, name))
125+
key = (domain, path, name)
124126
if key in self._expirations:
125-
del self._expirations[(domain, name)]
126-
self._cookies[domain].pop(name, None)
127+
del self._expirations[(domain, path, name)]
128+
self._cookies[(domain, path)].pop(name, None)
127129

128130
next_expiration = min(self._expirations.values(), default=self._max_time)
129131
try:
@@ -147,9 +149,11 @@ def __len__(self) -> int:
147149
def _do_expiration(self) -> None:
148150
self.clear(lambda x: False)
149151

150-
def _expire_cookie(self, when: datetime.datetime, domain: str, name: str) -> None:
152+
def _expire_cookie(
153+
self, when: datetime.datetime, domain: str, path: str, name: str
154+
) -> None:
151155
self._next_expiration = min(self._next_expiration, when)
152-
self._expirations[(domain, name)] = when
156+
self._expirations[(domain, path, name)] = when
153157

154158
def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
155159
"""Update cookies."""
@@ -211,7 +215,7 @@ def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> No
211215
) + datetime.timedelta(seconds=delta_seconds)
212216
except OverflowError:
213217
max_age_expiration = self._max_time
214-
self._expire_cookie(max_age_expiration, domain, name)
218+
self._expire_cookie(max_age_expiration, domain, path, name)
215219
except ValueError:
216220
cookie["max-age"] = ""
217221

@@ -220,11 +224,11 @@ def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> No
220224
if expires:
221225
expire_time = self._parse_date(expires)
222226
if expire_time:
223-
self._expire_cookie(expire_time, domain, name)
227+
self._expire_cookie(expire_time, domain, path, name)
224228
else:
225229
cookie["expires"] = ""
226230

227-
self._cookies[domain][name] = cookie
231+
self._cookies[(domain, path)][name] = cookie
228232

229233
self._do_expiration()
230234

tests/test_cookiejar.py

+22
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,28 @@ async def make_jar():
681681
# Assert that there is a cookie.
682682
assert len(jar) == 1
683683

684+
def test_path_filter_diff_folder_same_name(self) -> None:
685+
async def make_jar():
686+
return CookieJar(unsafe=True)
687+
688+
jar = self.loop.run_until_complete(make_jar())
689+
690+
jar.update_cookies(
691+
SimpleCookie("path-cookie=zero; Domain=pathtest.com; Path=/; ")
692+
)
693+
jar.update_cookies(
694+
SimpleCookie("path-cookie=one; Domain=pathtest.com; Path=/one; ")
695+
)
696+
self.assertEqual(len(jar), 2)
697+
698+
jar_filtered = jar.filter_cookies(URL("http://pathtest.com/"))
699+
self.assertEqual(len(jar_filtered), 1)
700+
self.assertEqual(jar_filtered["path-cookie"].value, "zero")
701+
702+
jar_filtered = jar.filter_cookies(URL("http://pathtest.com/one"))
703+
self.assertEqual(len(jar_filtered), 1)
704+
self.assertEqual(jar_filtered["path-cookie"].value, "one")
705+
684706

685707
async def test_dummy_cookie_jar() -> None:
686708
cookie = SimpleCookie("foo=bar; Domain=example.com;")

0 commit comments

Comments
 (0)