From c501784541ffe595f25cd62774d392270639c662 Mon Sep 17 00:00:00 2001 From: Arup Malakar Date: Wed, 16 May 2012 15:07:15 -0700 Subject: [PATCH] Issue #505: Allow disabling of cookie persistence/sending --- AUTHORS.rst | 1 + requests/api.py | 1 + requests/models.py | 11 ++++++++--- requests/sessions.py | 5 +++++ tests/test_cookies.py | 21 +++++++++++++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index b6002ec..ba3f85d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -100,3 +100,4 @@ Patches and Suggestions - Rohan Jain (crodjer) - Justin Barber - Roman Haritonov <@reclosedev> +- Arup Malakar diff --git a/requests/api.py b/requests/api.py index e0bf346..9c2445b 100644 --- a/requests/api.py +++ b/requests/api.py @@ -23,6 +23,7 @@ def request(method, url, **kwargs): :param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. + :param store_cookies: (optional) if ``False``, the received cookies as part of the HTTP response would be ignored. :param files: (optional) Dictionary of 'name': file-like-objects (or {'name': ('filename', fileobj)}) for multipart encoding upload. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) Float describing the timeout of the request. diff --git a/requests/models.py b/requests/models.py index beb8f14..9aea52e 100644 --- a/requests/models.py +++ b/requests/models.py @@ -60,6 +60,7 @@ class Request(object): params=dict(), auth=None, cookies=None, + store_cookies=True, timeout=None, redirect=False, allow_redirects=False, @@ -110,6 +111,9 @@ class Request(object): # Dictionary mapping protocol to the URL of the proxy (e.g. {'http': 'foo.bar:3128'}) self.proxies = dict(proxies or []) + #param store_cookies: (optional) if ``False``, the received cookies as part of the HTTP response would be ignored. + self.store_cookies = store_cookies + # If no proxies are given, allow configuration by environment variables # HTTP_PROXY and HTTPS_PROXY. if not self.proxies and self.config.get('trust_env'): @@ -197,8 +201,9 @@ class Request(object): # Set encoding. response.encoding = get_encoding_from_headers(response.headers) - # Add new cookies from the server. - extract_cookies_to_jar(self.cookies, self, resp) + # Add new cookies from the server. Don't if configured not to + if self.store_cookies: + extract_cookies_to_jar(self.cookies, self, resp) # Save cookies in Response. response.cookies = self.cookies @@ -460,7 +465,7 @@ class Request(object): return False def send(self, anyway=False, prefetch=False): - """Sends the request. Returns True of successful, False if not. + """Sends the request. Returns True if successful, False if not. If there was an HTTPError during transmission, self.response.status_code will contain the HTTPError code. diff --git a/requests/sessions.py b/requests/sessions.py index dd670dd..62fde5d 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -59,6 +59,7 @@ class Session(object): def __init__(self, headers=None, cookies=None, + store_cookies=True, auth=None, timeout=None, proxies=None, @@ -79,6 +80,7 @@ class Session(object): self.prefetch = prefetch self.verify = verify self.cert = cert + self.store_cookies = store_cookies for (k, v) in list(defaults.items()): self.config.setdefault(k, v) @@ -111,6 +113,7 @@ class Session(object): data=None, headers=None, cookies=None, + store_cookies=True, files=None, auth=None, timeout=None, @@ -132,6 +135,7 @@ class Session(object): :param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. + :param store_cookies: (optional) if ``False``, the received cookies as part of the HTTP response would be ignored. :param files: (optional) Dictionary of 'filename': file-like-objects for multipart encoding upload. :param auth: (optional) Auth tuple or callable to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) Float describing the timeout of the request. @@ -170,6 +174,7 @@ class Session(object): params=params, headers=headers, cookies=cookies, + store_cookies=store_cookies, files=files, auth=auth, hooks=hooks, diff --git a/tests/test_cookies.py b/tests/test_cookies.py index dca7d2c..a9fda18 100755 --- a/tests/test_cookies.py +++ b/tests/test_cookies.py @@ -102,6 +102,27 @@ class CookieTests(TestBaseMixin, unittest.TestCase): insecure_cookies_sent = json.loads(insecure_resp.text)['cookies'] self.assertEqual(insecure_cookies_sent, {}) + def test_disabled_cookie_persistence(self): + """Test that cookies are not persisted when configured accordingly.""" + + # Check the case when no cookie is passed as part of the request and the one in response is ignored + cookies = requests.get(httpbin('cookies', 'set', 'key', 'value'), store_cookies = False).cookies + self.assertIsNone(cookies.get("key")) + + # Test that the cookies passed while making the request still gets used and is available in response object. + # only the ones received from server is not saved + cookies_2 = requests.get(httpbin('cookies', 'set', 'key', 'value'), store_cookies = False,\ + cookies = {"key_2" : "value_2"}).cookies + self.assertEqual(len(cookies_2), 1) + self.assertEqual(cookies_2.get("key_2"), "value_2") + + # Use the session and make sure that the received cookie is not used in subsequent calls + s = requests.session() + s.get(httpbin('cookies', 'set', 'key', 'value'), store_cookies = False) + r = s.get(httpbin('cookies')) + self.assertEqual(json.loads(r.text)['cookies'], {}) + + class LWPCookieJarTest(TestBaseMixin, unittest.TestCase): """Check store/load of cookies to FileCookieJar's, specifically LWPCookieJar's.""" -- 2.7.4