Skip to content

Commit a673281

Browse files
committed
Merge pull request #145 from KeepSafe/cookies_share_fixes
share response cookies as soon as received (relates to #139)
2 parents d418ca5 + cd73bf1 commit a673281

File tree

5 files changed

+51
-46
lines changed

5 files changed

+51
-46
lines changed

aiohttp/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ def start(self, connection, read_until_eof=False):
629629
except http.cookies.CookieError as exc:
630630
client_log.warning(
631631
'Can not load response cookies: %s', exc)
632-
632+
connection.share_cookies(self.cookies)
633633
return self
634634

635635
def close(self, force=False):

aiohttp/connector.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ def release(self):
4646
self._transport = None
4747
self._wr = None
4848

49+
def share_cookies(self, cookies):
50+
if self._connector._share_cookies: # XXX
51+
self._connector.update_cookies(cookies)
52+
4953

5054
class BaseConnector(object):
5155
"""Base connector class.
@@ -178,8 +182,6 @@ def _release(self, key, req, transport, protocol):
178182
should_close = True
179183
else:
180184
should_close = resp.message.should_close
181-
if self._share_cookies and resp.cookies:
182-
self.update_cookies(resp.cookies.items())
183185

184186
if self._force_close:
185187
should_close = True

docs/client.rst

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -452,44 +452,6 @@ requests:
452452
.. note::
453453
By default ``share_cookies`` is set to ``False``.
454454

455-
.. _issue-139: https://github.com/KeepSafe/aiohttp/issues/139
456-
457-
.. note::
458-
Sharing cookies between requests must be clarified a bit.
459-
You might get into a `situation <issue-139_>`_ when it seems like cookies are
460-
not being shared between requests::
461-
462-
>>> conn = aiohttp.connector.TCPConnector(share_cookies=True)
463-
>>> # we assume example.com sets cookies on GET without redirect
464-
>>> resp1 = yield from aiohttp.request('get', 'http://example.com/',
465-
... connector=conn)
466-
>>> assert 'set-cookie' in resp1.headers # assume we got cookies in response
467-
>>> assert dict(conn.cookies) == {} # but no cookies to share!
468-
>>> resp2 = yield from aiohttp.request('get', 'http://example.com/',
469-
... connector=conn)
470-
>>> assert 'set-cookie' in resp2.headers # cookies again!
471-
472-
This happens because underlying connection handled by ``TCPConnector`` still
473-
belongs to ``resp1`` (because you might want to do something with response's body).
474-
As soon as you release that connection by ``yield'ing from`` ``resp.read()``,
475-
``resp.text()``, ``resp.json()`` or ``resp.release()`` the connection
476-
will become available (with cookies) for sebsequent requests::
477-
478-
>>> conn = aiohttp.connection.TCPConnector(share_cookies=True)
479-
>>> # assume the same
480-
>>> resp1 = yield from aiohttp.request('get', 'http://example.com/',
481-
... connector=conn)
482-
>>> assert 'set-cookie' in resp1.headers
483-
>>> assert dict(conn.cookies) == {}
484-
>>> # process response
485-
>>> do_something_with_response_or_release(resp1)
486-
>>> assert dict(conn.cookies) != {}
487-
>>> #
488-
>>> resp2 = yield from aiohttp.request('get', 'http://example.com/',
489-
... connector=conn)
490-
>>> assert 'set-cookie' not in resp2.headers
491-
>>> assert dict(conn.cookies) != {}
492-
493455

494456
Timeouts
495457
--------

tests/test_client_functional.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,25 @@ def test_set_cookies(self, m_log):
722722
m_log.warning.assert_called_with('Can not load response cookies: %s',
723723
mock.ANY)
724724

725+
def test_share_cookies(self):
726+
with test_utils.run_server(self.loop, router=Functional) as httpd:
727+
conn = aiohttp.TCPConnector(share_cookies=True, loop=self.loop)
728+
resp = self.loop.run_until_complete(
729+
client.request('get', httpd.url('cookies'),
730+
connector=conn, loop=self.loop))
731+
self.assertIn('SET-COOKIE', resp.headers)
732+
self.assertEqual(resp.cookies['c1'].value, 'cookie1')
733+
self.assertEqual(resp.cookies['c2'].value, 'cookie2')
734+
self.assertEqual(conn.cookies, resp.cookies)
735+
736+
resp2 = self.loop.run_until_complete(
737+
client.request('get', httpd.url('method', 'get'),
738+
connector=conn, loop=self.loop))
739+
self.assertNotIn('SET-COOKIE', resp2.headers)
740+
data = self.loop.run_until_complete(resp2.json())
741+
self.assertEqual(data['headers']['Cookie'],
742+
'c1=cookie1; c2=cookie2')
743+
725744
def test_chunked(self):
726745
with test_utils.run_server(self.loop, router=Functional) as httpd:
727746
r = self.loop.run_until_complete(

tests/test_connector.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,27 @@ def test_release(self):
5252
self.connector._release.assert_called_with(
5353
self.key, self.request, self.transport, self.protocol)
5454

55+
def test_no_share_cookies(self):
56+
connector = aiohttp.BaseConnector(share_cookies=False, loop=self.loop)
57+
58+
conn = Connection(
59+
connector, self.key, self.request,
60+
self.transport, self.protocol, self.loop)
61+
self.assertEqual(connector.cookies, {})
62+
conn.share_cookies({'c1': 'cookie1'})
63+
self.assertEqual(connector.cookies, {})
64+
65+
def test_share_cookies(self):
66+
connector = aiohttp.BaseConnector(share_cookies=True, loop=self.loop)
67+
68+
conn = Connection(
69+
connector, self.key, self.request,
70+
self.transport, self.protocol, self.loop)
71+
self.assertEqual(connector.cookies, {})
72+
conn.share_cookies({'c1': 'cookie1'})
73+
self.assertEqual(connector.cookies,
74+
http.cookies.SimpleCookie({'c1': 'cookie1'}))
75+
5576

5677
class BaseConnectorTests(unittest.TestCase):
5778

@@ -123,14 +144,14 @@ def test_release(self, m_time):
123144
resp = req.response = unittest.mock.Mock()
124145
resp.message.should_close = False
125146

126-
cookies = resp.cookies = http.cookies.SimpleCookie()
127-
cookies['c1'] = 'cookie1'
128-
cookies['c2'] = 'cookie2'
147+
# cookies = resp.cookies = http.cookies.SimpleCookie()
148+
# cookies['c1'] = 'cookie1'
149+
# cookies['c2'] = 'cookie2'
129150

130151
tr, proto = unittest.mock.Mock(), unittest.mock.Mock()
131152
conn._release(1, req, tr, proto)
132153
self.assertEqual(conn._conns[1][0], (tr, proto, 10))
133-
self.assertEqual(conn.cookies, dict(cookies.items()))
154+
# self.assertEqual(conn.cookies, dict(cookies.items()))
134155
self.assertTrue(conn._start_cleanup_task.called)
135156

136157
def test_release_close(self):
@@ -573,7 +594,8 @@ def test_request_port(self, ClientRequestMock):
573594
ClientRequestMock.return_value = proxy_req
574595

575596
loop_mock = unittest.mock.Mock()
576-
connector = aiohttp.ProxyConnector('http://proxy.example.com', loop=loop_mock)
597+
connector = aiohttp.ProxyConnector('http://proxy.example.com',
598+
loop=loop_mock)
577599

578600
tr, proto = unittest.mock.Mock(), unittest.mock.Mock()
579601
tr.get_extra_info.return_value = None

0 commit comments

Comments
 (0)