From 52a02166f8ed4c2f5bc3bdc7aaf5291530bf799f Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 23 Jul 2016 15:05:11 +0200 Subject: [PATCH] Add unsafe option for cookie jar --- CHANGES.txt | 7 +++++++ aiohttp/helpers.py | 7 ++++--- aiohttp/test_utils.py | 5 ++++- docs/client.rst | 22 ++++++++++++++++++++-- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 62a234e0989..e78169d8db4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,13 @@ CHANGES - Don't expose `aiohttp.__version__` +- Add unsafe parameter to CookieJar #968 + +- Use unsafe cookie jar in test client tools + +- Expose aiohttp.CookieJar name + + 0.22.1 (08-16-2016) ------------------- diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index d93d6c5bb21..25758ea4a3d 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -27,7 +27,7 @@ __all__ = ('BasicAuth', 'create_future', 'FormData', 'parse_mimetype', - 'Timeout') + 'Timeout', 'CookieJar') class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])): @@ -587,9 +587,10 @@ class CookieJar(AbstractCookieJar): DATE_YEAR_RE = re.compile("(\d{2,4})") - def __init__(self, *, loop=None): + def __init__(self, *, unsafe=False, loop=None): super().__init__(loop=loop) self._host_only_cookies = set() + self._unsafe = unsafe def _expire_cookie(self, when, name, DAY=24*3600): now = self._loop.time() @@ -608,7 +609,7 @@ def update_cookies(self, cookies, response_url=None): url_parsed = urlsplit(response_url or "") hostname = url_parsed.hostname - if is_ip_address(hostname): + if not self._unsafe and is_ip_address(hostname): # Don't accept cookies from IPs return diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index bb9e784eef4..2c6aa17a684 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -349,7 +349,10 @@ def __init__(self, app, protocol="http"): self._server = None if not loop.is_running(): loop.run_until_complete(self.start_server()) - self._session = ClientSession(loop=self._loop) + self._session = ClientSession( + loop=self._loop, + cookie_jar=aiohttp.CookieJar(unsafe=True, + loop=self._loop)) self._root = '{}://{}:{}'.format(protocol, self._address, self.port) self._closed = False diff --git a/docs/client.rst b/docs/client.rst index 7361d2f80d8..f30503b9525 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -386,6 +386,24 @@ You also can set default headers for all session requests:: :class:`~aiohttp.ClientSession` supports keep-alive requests and connection pooling out-of-the-box. +.. _aiohttp-client-cookie-safety: + +Cookie safety +------------- + +By default :class:`~aiohttp.ClientSession` uses strict version of +:class:`~aiohttp.CookieJar`. :rfc:`2109` explicitly forbids cookie +accepting from URLs with IP address instead of DNS name +(e.g. `http://127.0.0.1:80/cookie`). + +It's good but sometimes for testing we need to enable support for such +cookies. It should be done by passing `usafe=True` to +:class:`~aiohttp.CookieJar` constructor:: + + + jar = aiohttp.CookieJar(unsafe=True) + session = aiohttp.ClientSession(cookie_jar=jar) + Connectors ---------- @@ -421,8 +439,8 @@ In order to specify the nameservers to when resolving the hostnames, aiodns is required. from aiohttp.resolver import AsyncResolver - - + + resolver = AsyncResolver(nameservers=["8.8.8.8", "8.8.4.4"]) conn = aiohttp.TCPConnector(resolver=resolver)