From 2cb70cc8de372b0cbab56cea913018a4b98efccf Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 16 Jul 2016 14:27:26 +0300 Subject: [PATCH] Fix #967: large cookie expiration/max-age doesn't break an event loop from now --- CHANGES.txt | 7 +++++++ aiohttp/__init__.py | 2 +- aiohttp/helpers.py | 29 +++++++++++++++++++---------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 45b44a333c6..6eccd88e0d0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,13 @@ CHANGES ======= +0.22.1 (08-16-2016) +------------------- + +- Large cookie expiration/max-age doesn't break an event loop from now + (fixes #967) + + 0.22.0 (08-15-2016) ------------------- diff --git a/aiohttp/__init__.py b/aiohttp/__init__.py index 261d019fc85..faaad55ec5f 100644 --- a/aiohttp/__init__.py +++ b/aiohttp/__init__.py @@ -1,6 +1,6 @@ # This relies on each of the submodules having an __all__ variable. -__version__ = '0.22.0' +__version__ = '0.22.1' import multidict # noqa diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index 8a65ae6a9d0..256a55882b0 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -8,10 +8,12 @@ import io import os import re -from urllib.parse import quote, urlencode, urlsplit -from http.cookies import SimpleCookie, Morsel + from collections import namedtuple +from http.cookies import SimpleCookie, Morsel +from math import ceil from pathlib import Path +from urllib.parse import quote, urlencode, urlsplit import multidict @@ -589,9 +591,17 @@ def __init__(self, *, loop=None): super().__init__(loop=loop) self._host_only_cookies = set() - def _expire_cookie(self, name): - if name in self._cookies: - del self._cookies[name] + def _expire_cookie(self, when, name, DAY=24*3600): + now = self._loop.time() + delta = when - now + if delta <= 0: + # expired + self._cookies.pop(name, None) + if delta > DAY: + # Huge timeouts (more than 24 days) breaks event loop + self._loop.call_at(ceil(now+DAY), self._expire_cookie, when, name) + else: + self._loop.call_at(ceil(when), self._expire_cookie, when, name) def update_cookies(self, cookies, response_url=None): """Update cookies.""" @@ -636,8 +646,8 @@ def update_cookies(self, cookies, response_url=None): if max_age: try: delta_seconds = int(max_age) - self._loop.call_later( - delta_seconds, self._expire_cookie, name) + self._expire_cookie(self._loop.time() + delta_seconds, + name) except ValueError: cookie["max-age"] = "" @@ -645,9 +655,8 @@ def update_cookies(self, cookies, response_url=None): if not cookie["max-age"] and expires: expire_time = self._parse_date(expires) if expire_time: - self._loop.call_at( - expire_time.timestamp(), - self._expire_cookie, name) + self._expire_cookie(expire_time.timestamp(), + name) else: cookie["expires"] = ""