summaryrefslogtreecommitdiff
path: root/urllib3/util/sessioncontext.py
diff options
context:
space:
mode:
Diffstat (limited to 'urllib3/util/sessioncontext.py')
-rw-r--r--urllib3/util/sessioncontext.py74
1 files changed, 74 insertions, 0 deletions
diff --git a/urllib3/util/sessioncontext.py b/urllib3/util/sessioncontext.py
new file mode 100644
index 00000000..3b323dca
--- /dev/null
+++ b/urllib3/util/sessioncontext.py
@@ -0,0 +1,74 @@
+import time
+
+from ..packages.six.moves.http_cookiejar import (
+ DefaultCookiePolicy as PythonCookiePolicy,
+ CookieJar as PythonCookieJar
+)
+
+
+class DefaultCookiePolicy(PythonCookiePolicy):
+ """
+ The default urllib3 cookie policy - similar to the Python default,
+ but :param:`strict_ns_domain` is set to `DomainStrict` for security.
+ """
+ def __init__(self, *args, **kwargs):
+ policy = PythonCookiePolicy.DomainStrict
+ kwargs.setdefault('strict_ns_domain', policy)
+ # Old-style class on Python 2
+ PythonCookiePolicy.__init__(self, *args, **kwargs)
+
+
+class CookieJar(PythonCookieJar):
+
+ def __init__(self, policy=None):
+ if policy is None:
+ policy = DefaultCookiePolicy()
+ # Old-style class on Python 2
+ PythonCookieJar.__init__(self, policy=policy)
+
+ def add_cookie_header(self, request):
+ """
+ Add correct Cookie: header to Request object.
+ This is copied from and slightly modified from the stdlib version.
+ """
+ with self._cookies_lock:
+ self._policy._now = self._now = int(time.time())
+ cookies = self._cookies_for_request(request)
+ attrs = self._cookie_attrs(cookies)
+ # This is a modification; stdlib sets the entire cookie header
+ # and only if it's not there already. We're less picky.
+ if attrs:
+ request.add_cookies(*attrs)
+
+ self.clear_expired_cookies()
+
+
+class SessionContext(object):
+ """
+ Extensible class encapsulated by :class:`.SessionManager`; currently
+ used to manage cookies.
+
+ :param cookie_jar:
+ Used to pass a prebuilt :class:`CookieJar` into the
+ context to be used instead of an empty jar.
+ """
+
+ def __init__(self, cookie_jar=None):
+ # We unfortunately have to do it this way; empty cookie jars
+ # evaluate as falsey.
+ if cookie_jar is not None:
+ self.cookie_jar = cookie_jar
+ else:
+ self.cookie_jar = CookieJar()
+
+ def apply_to(self, request):
+ """
+ Applies changes from the context to the supplied :class:`.request.Request`.
+ """
+ self.cookie_jar.add_cookie_header(request)
+
+ def extract_from(self, response, request):
+ """
+ Extracts context modifications (new cookies, etc) from the response and stores them.
+ """
+ self.cookie_jar.extract_cookies(response, request)