From f5dd2858ae43eabfe54729c412bad97e893b6f9e Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Mon, 5 Dec 2016 19:49:24 -0800 Subject: [PATCH 1/7] fix cookies with cranky old servers --- aiohttp/client_reqrep.py | 3 ++- aiohttp/cookiejar.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index 27bcf8f2c44..b348447d6a2 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -185,7 +185,8 @@ def update_cookies(self, cookies): for name, value in cookies.items(): if isinstance(value, http.cookies.Morsel): - c[value.key] = value.value + # Set with Morsel to preserve coded_value based on version + c[value.key] = value else: c[name] = value diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py index b9dd25936e9..15ba783c79e 100644 --- a/aiohttp/cookiejar.py +++ b/aiohttp/cookiejar.py @@ -195,7 +195,9 @@ def filter_cookies(self, request_url=URL()): if is_not_secure and cookie["secure"]: continue - filtered[name] = cookie.value + # It's critical we use the Morsel so the coded_value + # (based on cookie version) is preserved + filtered[name] = cookie return filtered From 3f8cf9d0cc52ddc4482135ac6f1c6f63a691fce4 Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Tue, 6 Dec 2016 11:29:46 -0800 Subject: [PATCH 2/7] fix unit tests and add new test for quoted values --- tests/test_cookiejar.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py index 8c0f6dc9456..c6e92f5d0e8 100644 --- a/tests/test_cookiejar.py +++ b/tests/test_cookiejar.py @@ -240,8 +240,19 @@ def test_preserving_ip_domain_cookies(loop): )) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( header='Cookie:') - assert cookies_sent == ('Cookie: ip-cookie=second\r\n' - 'Cookie: shared-cookie=first') + assert cookies_sent == ('Cookie: ip-cookie=second; Domain=127.0.0.1; ' + 'Path=/\r\nCookie: shared-cookie=first') + + +def test_preserving_quoted_cookies(loop): + jar = CookieJar(loop=loop, unsafe=True) + jar.update_cookies(SimpleCookie( + "ip-cookie=\"second\"; Domain=127.0.0.1;" + )) + cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( + header='Cookie:') + assert cookies_sent == ('Cookie: ip-cookie=\"second\"; Domain=127.0.0.1; ' + 'Path=/') def test_ignore_domain_ending_with_dot(loop): @@ -249,11 +260,13 @@ def test_ignore_domain_ending_with_dot(loop): jar.update_cookies(SimpleCookie("cookie=val; Domain=example.com.;"), URL("http://www.example.com")) cookies_sent = jar.filter_cookies(URL("http://www.example.com/")) - assert cookies_sent.output(header='Cookie:') == "Cookie: cookie=val" + assert cookies_sent.output(header='Cookie:') \ + == "Cookie: cookie=val; Domain=www.example.com; Path=/" cookies_sent = jar.filter_cookies(URL("http://example.com/")) assert cookies_sent.output(header='Cookie:') == "" + class TestCookieJarBase(unittest.TestCase): def setUp(self): From 85a7e43c0eea936bf368f8b15ad43fc0a51699c7 Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Tue, 6 Dec 2016 11:39:03 -0800 Subject: [PATCH 3/7] fix extra line --- tests/test_cookiejar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py index c6e92f5d0e8..c6cb7ed960e 100644 --- a/tests/test_cookiejar.py +++ b/tests/test_cookiejar.py @@ -266,7 +266,6 @@ def test_ignore_domain_ending_with_dot(loop): assert cookies_sent.output(header='Cookie:') == "" - class TestCookieJarBase(unittest.TestCase): def setUp(self): From 5e27754ec5b414bc6ca3d107e17043a8fb8fb940 Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Tue, 6 Dec 2016 11:52:34 -0800 Subject: [PATCH 4/7] pycharm did the wrong thing --- tests/test_cookiejar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py index c6cb7ed960e..e249eca824d 100644 --- a/tests/test_cookiejar.py +++ b/tests/test_cookiejar.py @@ -261,7 +261,7 @@ def test_ignore_domain_ending_with_dot(loop): URL("http://www.example.com")) cookies_sent = jar.filter_cookies(URL("http://www.example.com/")) assert cookies_sent.output(header='Cookie:') \ - == "Cookie: cookie=val; Domain=www.example.com; Path=/" + == "Cookie: cookie=val; Domain=www.example.com; Path=/" cookies_sent = jar.filter_cookies(URL("http://example.com/")) assert cookies_sent.output(header='Cookie:') == "" From 40f8f7dcea7718191edb0783c0ce385d9d854a72 Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Tue, 6 Dec 2016 13:22:17 -0800 Subject: [PATCH 5/7] update docs --- CHANGES.rst | 2 +- CONTRIBUTORS.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 408825c8140..a607b3f46a0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -34,7 +34,7 @@ CHANGES - Fix bugs related to the use of unicode hostnames #1444 -- +- Preserve cookie quoting/escaping #1453 - diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 6062077bdb0..db9a03839f6 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -10,6 +10,7 @@ Alexander Bayandin Alexander Karpinsky Alexander Koshevoy Alexander Malev +Alexander Mohr Alexander Shorin Alexander Travov Alexandru Mihai From 48885591c76fb4fd6e4227c812505002610efc84 Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Wed, 7 Dec 2016 10:09:33 -0800 Subject: [PATCH 6/7] need to filter out extra properties in morsels --- aiohttp/client_reqrep.py | 6 ++++-- aiohttp/cookiejar.py | 4 +++- tests/test_cookiejar.py | 14 +++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index b348447d6a2..3b5b6c0d5fb 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -185,8 +185,10 @@ def update_cookies(self, cookies): for name, value in cookies.items(): if isinstance(value, http.cookies.Morsel): - # Set with Morsel to preserve coded_value based on version - c[value.key] = value + # Preserve coded_value + mrsl_val = value.get(value.key, http.cookies.Morsel()) + mrsl_val.set(value.key, value.value, value.coded_value) + c[name] = mrsl_val else: c[name] = value diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py index 15ba783c79e..78b666f8dac 100644 --- a/aiohttp/cookiejar.py +++ b/aiohttp/cookiejar.py @@ -197,7 +197,9 @@ def filter_cookies(self, request_url=URL()): # It's critical we use the Morsel so the coded_value # (based on cookie version) is preserved - filtered[name] = cookie + mrsl_val = cookie.get(cookie.key, Morsel()) + mrsl_val.set(cookie.key, cookie.value, cookie.coded_value) + filtered[name] = mrsl_val return filtered diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py index e249eca824d..f8f3468cad9 100644 --- a/tests/test_cookiejar.py +++ b/tests/test_cookiejar.py @@ -240,10 +240,12 @@ def test_preserving_ip_domain_cookies(loop): )) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( header='Cookie:') - assert cookies_sent == ('Cookie: ip-cookie=second; Domain=127.0.0.1; ' - 'Path=/\r\nCookie: shared-cookie=first') + assert cookies_sent == ('Cookie: ip-cookie=second\r\n' + 'Cookie: shared-cookie=first') +test_preserving_ip_domain_cookies(None) + def test_preserving_quoted_cookies(loop): jar = CookieJar(loop=loop, unsafe=True) jar.update_cookies(SimpleCookie( @@ -251,8 +253,7 @@ def test_preserving_quoted_cookies(loop): )) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( header='Cookie:') - assert cookies_sent == ('Cookie: ip-cookie=\"second\"; Domain=127.0.0.1; ' - 'Path=/') + assert cookies_sent == 'Cookie: ip-cookie=\"second\"' def test_ignore_domain_ending_with_dot(loop): @@ -260,8 +261,7 @@ def test_ignore_domain_ending_with_dot(loop): jar.update_cookies(SimpleCookie("cookie=val; Domain=example.com.;"), URL("http://www.example.com")) cookies_sent = jar.filter_cookies(URL("http://www.example.com/")) - assert cookies_sent.output(header='Cookie:') \ - == "Cookie: cookie=val; Domain=www.example.com; Path=/" + assert cookies_sent.output(header='Cookie:') == "Cookie: cookie=val" cookies_sent = jar.filter_cookies(URL("http://example.com/")) assert cookies_sent.output(header='Cookie:') == "" @@ -272,7 +272,7 @@ def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) - # N.B. those need to be overriden in child test cases + # N.B. those need to be overridden in child test cases self.jar = CookieJar(loop=self.loop) def tearDown(self): From 2d58bae26504f25a86382fa65e21f3ff0579508a Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Wed, 7 Dec 2016 10:16:21 -0800 Subject: [PATCH 7/7] remove debug code --- tests/test_cookiejar.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py index f8f3468cad9..9d487f8654a 100644 --- a/tests/test_cookiejar.py +++ b/tests/test_cookiejar.py @@ -244,8 +244,6 @@ def test_preserving_ip_domain_cookies(loop): 'Cookie: shared-cookie=first') -test_preserving_ip_domain_cookies(None) - def test_preserving_quoted_cookies(loop): jar = CookieJar(loop=loop, unsafe=True) jar.update_cookies(SimpleCookie(