diff --git a/AUTHORS.rst b/AUTHORS.rst index d24cf214..0ab42cef 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -101,3 +101,4 @@ Patches and Suggestions - Justin Barber - Roman Haritonov <@reclosedev> - Josh Imhoff +- Arup Malakar diff --git a/requests/api.py b/requests/api.py index 4fc30709..cc6a1c7b 100644 --- a/requests/api.py +++ b/requests/api.py @@ -25,6 +25,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 e60e67b1..79a3bc36 100644 --- a/requests/models.py +++ b/requests/models.py @@ -59,6 +59,7 @@ class Request(object): params=dict(), auth=None, cookies=None, + store_cookies=True, timeout=None, redirect=False, allow_redirects=False, @@ -109,6 +110,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'): @@ -196,8 +200,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 diff --git a/requests/sessions.py b/requests/sessions.py index aa90ecc7..e047ce56 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -60,6 +60,7 @@ class Session(object): def __init__(self, headers=None, cookies=None, + store_cookies=True, auth=None, timeout=None, proxies=None, @@ -80,6 +81,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, deepcopy(v)) @@ -112,6 +114,7 @@ class Session(object): data=None, headers=None, cookies=None, + store_cookies=True, files=None, auth=None, timeout=None, @@ -133,6 +136,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. @@ -171,6 +175,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 dca7d2c4..a9fda180 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."""