mostly complete cookie support based on cookiejar
authormiguel <miguel@immunityinc.com>
Fri, 3 Feb 2012 20:12:41 +0000 (15:12 -0500)
committerShivaram Lingamneni <slingamn@cs.stanford.edu>
Wed, 2 May 2012 00:00:19 +0000 (17:00 -0700)
requests/models.py
requests/packages/oreos/cookiejar.py
requests/sessions.py

index be6a4edca41f54bc5df0f23e17ab0af08086bbe9..4e6f26a66169490bd211e28d826992f68351ccea 100644 (file)
@@ -15,6 +15,7 @@ from .structures import CaseInsensitiveDict
 from .status_codes import codes
 
 from .auth import HTTPBasicAuth, HTTPProxyAuth
+from .packages.oreos.cookiejar import CookieJar
 from .packages.urllib3.response import HTTPResponse
 from .packages.urllib3.exceptions import MaxRetryError, LocationParseError
 from .packages.urllib3.exceptions import SSLError as _SSLError
@@ -126,7 +127,14 @@ class Request(object):
         self.auth = auth
 
         #: CookieJar to attach to :class:`Request <Request>`.
-        self.cookies = dict(cookies or [])
+        if isinstance(cookies, CookieJar):
+            self.cookies = cookies
+        else:
+            self.cookies = CookieJar()
+            
+            # Add passed cookies in.
+            if cookies is not None:
+                self.cookies.update(cookies)
 
         #: True if Request has been sent.
         self.sent = False
@@ -182,27 +190,26 @@ class Request(object):
             # Pass settings over.
             response.config = self.config
 
+            # Save original response for later.
+            response.raw = resp
+            response.url = self.full_url
+
             if resp:
 
                 # Fallback to None if there's no status_code, for whatever reason.
                 response.status_code = getattr(resp, 'status', None)
-
+                
                 # Make headers case-insensitive.
                 response.headers = CaseInsensitiveDict(getattr(resp, 'headers', None))
 
                 # Set encoding.
                 response.encoding = get_encoding_from_headers(response.headers)
 
-                # Start off with our local cookies.
-                cookies = self.cookies or dict()
-
                 # Add new cookies from the server.
-                if 'set-cookie' in response.headers:
-                    cookie_header = response.headers['set-cookie']
-                    cookies = dict_from_string(cookie_header)
+                self.cookies.extract_cookies(response, self)
 
                 # Save cookies in Response.
-                response.cookies = cookies
+                response.cookies = self.cookies
 
                 # No exceptions were harmed in the making of this request.
                 response.error = getattr(resp, 'error', None)
@@ -220,8 +227,6 @@ class Request(object):
 
         r = build(resp)
 
-        self.cookies.update(r.cookies)
-
         if r.status_code in REDIRECT_STATI and not self.redirect:
 
             while (('location' in r.headers) and
@@ -299,13 +304,11 @@ class Request(object):
 
                 request.send()
                 r = request.response
-                self.cookies.update(r.cookies)
 
             r.history = history
 
         self.response = r
         self.response.request = self
-        self.response.cookies.update(self.cookies)
 
     @staticmethod
     def _encode_params(data):
@@ -573,19 +576,13 @@ class Request(object):
 
         if not self.sent or anyway:
 
-            if self.cookies:
-
-                # Skip if 'cookie' header is explicitly set.
-                if 'cookie' not in self.headers:
-
-                    # Simple cookie with our dict.
-                    c = SimpleCookie()
-                    for (k, v) in list(self.cookies.items()):
-                        c[k] = v
-
-                    # Turn it into a header.
-                    cookie_header = c.output(header='', sep='; ').strip()
+            # Skip if 'cookie' header is explicitly set.
+            if 'cookie' not in self.headers:
 
+                # Turn it into a header.
+                cookie_header = self.cookies.get_header(self)
+                
+                if cookie_header:
                     # Attach Cookie header to request.
                     self.headers['Cookie'] = cookie_header
 
index 0e21e443c7c52792dc94313e8b167ffd5f7f680e..9327e158dfc391e922f2038527f211a2a5d9a963 100644 (file)
@@ -1,3 +1,8 @@
+"""
+Wrapper for CookieJar allow dict-like access.
+Ideally there would be wrappers for LWPCookieJar and MozillaCookieJar as well.
+"""
+
 import urlparse
 import Cookie
 from Cookie import Morsel
@@ -18,8 +23,8 @@ class MockRequest:
         return urlparse.urlparse(self._r.full_url).netloc
     
     def get_origin_req_host(self):
-        if self._r.history:
-            r = self._r.history[0]
+        if self._r.response.history:
+            r = self._r.response.history[0]
             return urlparse.urlparse(r).netloc
         else:
             return self.get_host()
@@ -42,7 +47,7 @@ class MockRequest:
     
     def is_unverifiable(self):
         # unverifiable == redirected
-        return bool(self.history)
+        return bool(self._r.response.history)
 
 class MockResponse:
     """
@@ -57,7 +62,7 @@ class MockResponse:
     def getheaders(self, name):
         self._r.msg.getheaders(name)
 
-class CookieJar(cookielib.LWPCookieJar, collections.MutableMapping):
+class CookieJar(cookielib.CookieJar, collections.MutableMapping):
     def extract_cookies(self, response, request):
         if response.raw._original_response:
             req = MockRequest(request)
index f032cdcf5cfc32b17a375127b2128ae07201f111..141bbf692375896f4b132f0644cc11c6319a409e 100644 (file)
@@ -14,7 +14,7 @@ from .models import Request
 from .hooks import dispatch_hook
 from .utils import header_expand
 from .packages.urllib3.poolmanager import PoolManager
-
+from .packages.oreos.cookiejar import CookieJar
 
 def merge_kwargs(local_kwarg, default_kwarg):
     """Merges kwarg dictionaries.
@@ -69,7 +69,6 @@ class Session(object):
         cert=None):
 
         self.headers = headers or {}
-        self.cookies = cookies or {}
         self.auth = auth
         self.timeout = timeout
         self.proxies = proxies or {}
@@ -86,11 +85,14 @@ class Session(object):
         self.init_poolmanager()
 
         # Set up a CookieJar to be used by default
-        self.cookies = {}
-
-        # Add passed cookies in.
-        if cookies is not None:
-            self.cookies.update(cookies)
+        if isinstance(cookies, CookieJar):
+            self.cookies = cookies
+        else:
+            self.cookies = CookieJar()
+            
+            # Add passed cookies in.
+            if cookies is not None:
+                self.cookies.update(cookies)
 
     def init_poolmanager(self):
         self.poolmanager = PoolManager(
@@ -148,7 +150,6 @@ class Session(object):
         method = str(method).upper()
 
         # Default empty dicts for dict params.
-        cookies = {} if cookies is None else cookies
         data = {} if data is None else data
         files = {} if files is None else files
         headers = {} if headers is None else headers