Skip to content

Commit

Permalink
Handle response with multiple same name cookies
Browse files Browse the repository at this point in the history
  • Loading branch information
alandtse committed Jun 15, 2020
1 parent 6a5ab96 commit 75d59d5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
9 changes: 6 additions & 3 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import traceback
import warnings
from hashlib import md5, sha1, sha256
from http.cookies import CookieError, Morsel, SimpleCookie
from http.cookies import BaseCookie, CookieError, Morsel, SimpleCookie
from types import MappingProxyType, TracebackType
from typing import ( # noqa
TYPE_CHECKING,
Expand Down Expand Up @@ -689,7 +689,7 @@ def __init__(self, method: str, url: URL, *,
assert isinstance(url, URL)

self.method = method
self.cookies = SimpleCookie()
self.cookies = [] # type: List[Tuple[str, BaseCookie[str]]]

self._real_url = url
self._url = url.with_fragment(None)
Expand Down Expand Up @@ -877,7 +877,10 @@ async def start(self, connection: 'Connection') -> 'ClientResponse':
# cookies
for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):
try:
self.cookies.load(hdr)
new_cookie = SimpleCookie()
new_cookie.load(hdr)
new_cookie_list = list(new_cookie.items())
self.cookies = self.cookies + new_cookie_list # type: ignore
except CookieError as exc:
client_logger.warning(
'Can not load response cookies: %s', exc)
Expand Down
56 changes: 56 additions & 0 deletions tests/test_client_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,62 @@ async def create_connection(req, traces, timeout):
await session.close()
conn.close()

async def test_custom_req_rep_same_cookie_diff_domain(loop) -> None:
conn = None

class CustomResponse(ClientResponse):

async def start(self, connection, read_until_eof=False):
nonlocal conn
conn = connection
self.status = 123
self.reason = 'Test OK'
self._headers = CIMultiDictProxy(CIMultiDict())
self.cookies = (
list(SimpleCookie("cookie=first; Domain=example.com; Path=/; ").items()) +
list(SimpleCookie("cookie=second; Domain=test1.example.com; Path=/; ").items()) +
list(SimpleCookie("cookie=third; Domain=test2.example.com; Path=/; ").items()))
return

called = False

class CustomRequest(ClientRequest):

async def send(self, conn):
resp = self.response_class(self.method,
self.url,
writer=self._writer,
continue100=self._continue,
timer=self._timer,
request_info=self.request_info,
traces=self._traces,
loop=self.loop,
session=self._session)
self.response = resp
nonlocal called
called = True
return resp

async def create_connection(req, traces, timeout):
assert isinstance(req, CustomRequest)
return mock.Mock()
connector = BaseConnector(loop=loop)
connector._create_connection = create_connection

session = aiohttp.ClientSession(
request_class=CustomRequest,
response_class=CustomResponse,
connector=connector,
loop=loop)

resp = await session.request(
'get', URL('http://example.com/path/to'))
assert isinstance(resp, CustomResponse)
assert called
assert len(resp.cookies) == 3
resp.close()
await session.close()
conn.close()

def test_verify_ssl_false_with_ssl_context(loop, ssl_ctx) -> None:
with pytest.warns(DeprecationWarning):
Expand Down

0 comments on commit 75d59d5

Please sign in to comment.