From 36093e69c70b9b24dd1e007befa35ad891313f51 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sun, 5 Apr 2015 21:27:33 -0500 Subject: [PATCH] Copy a PreparedRequest's CookieJar reliably When a PreparedRequests's cookie jar is not a RequestsCookieJar instance, it will not have a "copy" method. By adding _copy_cookie_jar we can reliably copy cookie jars so that we have an actual copy instead of the same instance on different prepared requests. This also updates the RequestsCookieJar.update logic to create copies of cookies from the other jar. Closes #2527 --- requests/cookies.py | 18 +++++++++++++++++- requests/models.py | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/requests/cookies.py b/requests/cookies.py index 6969fe5c..1fbc934c 100644 --- a/requests/cookies.py +++ b/requests/cookies.py @@ -6,6 +6,7 @@ Compatibility code to be able to use `cookielib.CookieJar` with requests. requests.utils imports from here, so be careful with imports. """ +import copy import time import collections from .compat import cookielib, urlparse, urlunparse, Morsel @@ -302,7 +303,7 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping): """Updates this jar with cookies from another CookieJar or dict-like""" if isinstance(other, cookielib.CookieJar): for cookie in other: - self.set_cookie(cookie) + self.set_cookie(copy.copy(cookie)) else: super(RequestsCookieJar, self).update(other) @@ -359,6 +360,21 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping): return new_cj +def _copy_cookie_jar(jar): + if jar is None: + return None + + if hasattr(jar, 'copy'): + # We're dealing with an instane of RequestsCookieJar + return jar.copy() + # We're dealing with a generic CookieJar instance + new_jar = copy.copy(jar) + new_jar.clear() + for cookie in jar: + new_jar.set_cookie(copy.copy(cookie)) + return new_jar + + def create_cookie(name, value, **kwargs): """Make a cookie from underspecified parameters. diff --git a/requests/models.py b/requests/models.py index cb153aa5..12304adb 100644 --- a/requests/models.py +++ b/requests/models.py @@ -15,7 +15,7 @@ from .hooks import default_hooks from .structures import CaseInsensitiveDict from .auth import HTTPBasicAuth -from .cookies import cookiejar_from_dict, get_cookie_header +from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar from .packages.urllib3.fields import RequestField from .packages.urllib3.filepost import encode_multipart_formdata from .packages.urllib3.util import parse_url @@ -320,7 +320,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): p.method = self.method p.url = self.url p.headers = self.headers.copy() if self.headers is not None else None - p._cookies = self._cookies.copy() if self._cookies is not None else None + p._cookies = _copy_cookie_jar(self._cookies) p.body = self.body p.hooks = self.hooks return p