Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Doc/library/http.cookiejar.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,16 @@ The following classes are provided:
from / returned to the server.


.. class:: DefaultCookiePolicy( blocked_domains=None, allowed_domains=None, netscape=True, rfc2965=False, rfc2109_as_netscape=None, hide_cookie2=False, strict_domain=False, strict_rfc2965_unverifiable=True, strict_ns_unverifiable=False, strict_ns_domain=DefaultCookiePolicy.DomainLiberal, strict_ns_set_initial_dollar=False, strict_ns_set_path=False )
.. class:: DefaultCookiePolicy( blocked_domains=None, allowed_domains=None, netscape=True, rfc2965=False, rfc2109_as_netscape=None, hide_cookie2=False, strict_domain=False, strict_rfc2965_unverifiable=True, strict_ns_unverifiable=False, strict_ns_domain=DefaultCookiePolicy.DomainLiberal, strict_ns_set_initial_dollar=False, strict_ns_set_path=False, secure_protocols=("https", "wss") )

Constructor arguments should be passed as keyword arguments only.
*blocked_domains* is a sequence of domain names that we never accept cookies
from, nor return cookies to. *allowed_domains* if not :const:`None`, this is a
sequence of the only domains for which we accept and return cookies. For all
other arguments, see the documentation for :class:`CookiePolicy` and
:class:`DefaultCookiePolicy` objects.
sequence of the only domains for which we accept and return cookies.
*secure_protocols* is a sequence of protocols for which secure cookies can be
added to. By default *https* and *wss* (secure websocket) are considered
secure protocols. For all other arguments, see the documentation for
:class:`CookiePolicy` and :class:`DefaultCookiePolicy` objects.

:class:`DefaultCookiePolicy` implements the standard accept / reject rules for
Netscape and :rfc:`2965` cookies. By default, :rfc:`2109` cookies (ie. cookies
Expand Down
4 changes: 3 additions & 1 deletion Lib/http/cookiejar.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@ def __init__(self,
strict_ns_domain=DomainLiberal,
strict_ns_set_initial_dollar=False,
strict_ns_set_path=False,
secure_protocols=("https", "wss")
):
"""Constructor arguments should be passed as keyword arguments only."""
self.netscape = netscape
Expand All @@ -890,6 +891,7 @@ def __init__(self,
self.strict_ns_domain = strict_ns_domain
self.strict_ns_set_initial_dollar = strict_ns_set_initial_dollar
self.strict_ns_set_path = strict_ns_set_path
self.secure_protocols = secure_protocols

if blocked_domains is not None:
self._blocked_domains = tuple(blocked_domains)
Expand Down Expand Up @@ -1116,7 +1118,7 @@ def return_ok_verifiability(self, cookie, request):
return True

def return_ok_secure(self, cookie, request):
if cookie.secure and request.type != "https":
if cookie.secure and request.type not in self.secure_protocols:
_debug(" secure cookie with non-secure request")
return False
return True
Expand Down
55 changes: 55 additions & 0 deletions Lib/test/test_http_cookiejar.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,61 @@ def test_secure(self):
c._cookies["www.acme.com"]["/"]["foo2"].secure,
"secure cookie registered non-secure")

def test_secure_block(self):
pol = DefaultCookiePolicy()
c = CookieJar(policy=pol)

headers = ["Set-Cookie: session=narf; secure; path=/"]
req = urllib.request.Request("https://www.acme.com/")
res = FakeResponse(headers, "https://www.acme.com/")
c.extract_cookies(res, req)
self.assertEqual(len(c), 1)

req = urllib.request.Request("https://www.acme.com/")
c.add_cookie_header(req)
self.assertTrue(req.has_header("Cookie"))

req = urllib.request.Request("http://www.acme.com/")
c.add_cookie_header(req)
self.assertFalse(req.has_header("Cookie"))

# secure websocket protocol
req = urllib.request.Request("wss://www.acme.com/")
c.add_cookie_header(req)
self.assertTrue(req.has_header("Cookie"))

# non-secure websocket protocol
req = urllib.request.Request("ws://www.acme.com/")
c.add_cookie_header(req)
self.assertFalse(req.has_header("Cookie"))

def test_custom_secure_protocols(self):
pol = DefaultCookiePolicy(secure_protocols=["foos"])
c = CookieJar(policy=pol)

headers = ["Set-Cookie: session=narf; secure; path=/"]
req = urllib.request.Request("https://www.acme.com/")
res = FakeResponse(headers, "https://www.acme.com/")
c.extract_cookies(res, req)
self.assertEqual(len(c), 1)

# test https removed from secure protocol list
req = urllib.request.Request("https://www.acme.com/")
c.add_cookie_header(req)
self.assertFalse(req.has_header("Cookie"))

req = urllib.request.Request("http://www.acme.com/")
c.add_cookie_header(req)
self.assertFalse(req.has_header("Cookie"))

req = urllib.request.Request("foos://www.acme.com/")
c.add_cookie_header(req)
self.assertTrue(req.has_header("Cookie"))

req = urllib.request.Request("foo://www.acme.com/")
c.add_cookie_header(req)
self.assertFalse(req.has_header("Cookie"))

def test_quote_cookie_value(self):
c = CookieJar(policy=DefaultCookiePolicy(rfc2965=True))
interact_2965(c, "http://www.acme.com/", r'foo=\b"a"r; Version=1')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added *secure_protocols* argument to *http.cookiejar.DefaultCookiePolicy* to
allow for tweaking of protocols and also to add support by default for
*wss*, the secure websocket protocol.