Skip to content

Commit

Permalink
Defer creation of cookies for client responses until needed (#10029)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Nov 24, 2024
1 parent cdc01cd commit 5f5729d
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES/10029.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improved performance of creating :class:`aiohttp.ClientResponse` objects when there are no cookies -- by :user:`bdraco`.
2 changes: 1 addition & 1 deletion aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ async def _request(
raise
raise ClientOSError(*exc.args) from exc

if cookies := resp.cookies:
if cookies := resp._cookies:
self._cookie_jar.update_cookies(cookies, resp.url)

# redirects
Expand Down
25 changes: 19 additions & 6 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ class ClientResponse(HeadersMixin):
_raw_headers: RawHeaders = None # type: ignore[assignment]

_connection: Optional["Connection"] = None # current connection
_cookies: Optional[SimpleCookie] = None
_continue: Optional["asyncio.Future[bool]"] = None
_source_traceback: Optional[traceback.StackSummary] = None
_session: Optional["ClientSession"] = None
Expand Down Expand Up @@ -797,7 +798,6 @@ def __init__(
super().__init__()

self.method = method
self.cookies = SimpleCookie()

self._real_url = url
self._url = url.with_fragment(None) if url.raw_fragment else url
Expand Down Expand Up @@ -846,6 +846,16 @@ def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
else:
writer.add_done_callback(self.__reset_writer)

@property
def cookies(self) -> SimpleCookie:
if self._cookies is None:
self._cookies = SimpleCookie()
return self._cookies

@cookies.setter
def cookies(self, cookies: SimpleCookie) -> None:
self._cookies = cookies

@reify
def url(self) -> URL:
return self._url
Expand Down Expand Up @@ -1005,11 +1015,14 @@ async def start(self, connection: "Connection") -> "ClientResponse":
self.content = payload

# cookies
for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):
try:
self.cookies.load(hdr)
except CookieError as exc:
client_logger.warning("Can not load response cookies: %s", exc)
if cookie_hdrs := self.headers.getall(hdrs.SET_COOKIE, ()):
cookies = SimpleCookie()
for hdr in cookie_hdrs:
try:
cookies.load(hdr)
except CookieError as exc:
client_logger.warning("Can not load response cookies: %s", exc)
self._cookies = cookies
return self

def _response_eof(self) -> None:
Expand Down
19 changes: 19 additions & 0 deletions tests/test_client_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,25 @@ def side_effect(*args: object, **kwargs: object) -> "asyncio.Future[bytes]":
)


def test_response_cookies(
loop: asyncio.AbstractEventLoop, session: ClientSession
) -> None:
response = ClientResponse(
"get",
URL("http://python.org"),
request_info=mock.Mock(),
writer=WriterMock(),
continue100=None,
timer=TimerNoop(),
traces=[],
loop=loop,
session=session,
)
cookies = response.cookies
# Ensure the same cookies object is returned each time
assert response.cookies is cookies


def test_response_real_url(
loop: asyncio.AbstractEventLoop, session: ClientSession
) -> None:
Expand Down

0 comments on commit 5f5729d

Please sign in to comment.