diff --git a/httpie/client.py b/httpie/client.py index 65f88e43..ff596bbd 100644 --- a/httpie/client.py +++ b/httpie/client.py @@ -11,7 +11,6 @@ from urllib.parse import urlparse, urlunparse import requests # noinspection PyPackageRequirements import urllib3 -from requests.cookies import remove_cookie_by_name from httpie import __version__ from httpie.cli.dicts import RequestHeadersDict @@ -96,9 +95,11 @@ def collect_messages( **send_kwargs_merged, **send_kwargs, ) - expired_cookies += get_expired_cookies( - headers=response.raw._original_response.msg._headers - ) + + # noinspection PyProtectedMember + expired_cookies += get_expired_cookies( + headers=response.raw._original_response.msg._headers + ) response_count += 1 if response.next: @@ -116,6 +117,7 @@ def collect_messages( if httpie_session.is_new() or not args.session_read_only: httpie_session.cookies = requests_session.cookies httpie_session.remove_cookies( + # TODO: take path & domain into account? cookie['name'] for cookie in expired_cookies ) httpie_session.save() diff --git a/httpie/sessions.py b/httpie/sessions.py index 5750f3de..c8581fa6 100644 --- a/httpie/sessions.py +++ b/httpie/sessions.py @@ -9,7 +9,7 @@ from typing import Iterable, Optional, Union from urllib.parse import urlsplit from requests.auth import AuthBase -from requests.cookies import RequestsCookieJar, create_cookie, remove_cookie_by_name +from requests.cookies import RequestsCookieJar, create_cookie from httpie.cli.dicts import RequestHeadersDict from httpie.config import BaseConfigDict, DEFAULT_CONFIG_DIR diff --git a/httpie/utils.py b/httpie/utils.py index d47f3531..41bdbdd4 100644 --- a/httpie/utils.py +++ b/httpie/utils.py @@ -89,25 +89,25 @@ def get_content_type(filename): return content_type -def get_expired_cookies(headers: List[Tuple[str, str]], curr_timestamp: float = None) -> List[dict]: - expired_cookies = [] - cookie_headers = [] - curr_timestamp = curr_timestamp or time.time() - - for header_name, content in headers: - if header_name == 'Set-Cookie': - cookie_headers.append(content) - - extracted_cookies = [ - dict(cookie, name=cookie[0][0]) - for cookie in parse_ns_headers(cookie_headers) +def get_expired_cookies( + headers: List[Tuple[str, str]], + now: float = None +) -> List[dict]: + now = now or time.time() + attr_sets: List[Tuple[str, str]] = parse_ns_headers( + value for name, value in headers + if name.lower() == 'set-cookie' + ) + cookies = [ + # The first attr name is the cookie name. + dict(attrs[1:], name=attrs[0][0]) + for attrs in attr_sets + ] + return [ + { + 'name': cookie['name'], + 'path': cookie.get('path', '/') + } + for cookie in cookies + if cookie.get('expires', float('Inf')) <= now ] - - for cookie in extracted_cookies: - if "expires" in cookie and cookie['expires'] <= curr_timestamp: - expired_cookies.append({ - 'name': cookie['name'], - 'path': cookie.get('path', '/') - }) - - return expired_cookies diff --git a/tests/test_sessions.py b/tests/test_sessions.py index b5474310..6cb5ce0e 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -193,6 +193,12 @@ class TestSession(SessionTestBase): class TestExpiredCookies: + def setup_method(self, method): + self.config_dir = mk_config_dir() + + def teardown_method(self, method): + shutil.rmtree(self.config_dir) + @pytest.mark.parametrize( argnames=['initial_cookie', 'expired_cookie'], argvalues=[ @@ -201,14 +207,11 @@ class TestExpiredCookies: ] ) def test_removes_expired_cookies_from_session_obj(self, initial_cookie, expired_cookie, httpbin): - config_dir = mk_config_dir() - session = Session(config_dir) + session = Session(self.config_dir) session['cookies'] = initial_cookie session.remove_cookies([expired_cookie]) assert expired_cookie not in session.cookies - shutil.rmtree(config_dir) - def test_expired_cookies(self, httpbin): orig_session = { 'cookies': { @@ -220,8 +223,7 @@ class TestExpiredCookies: }, } } - config_dir = mk_config_dir() - session_path = config_dir / 'test-session.json' + session_path = self.config_dir / 'test-session.json' session_path.write_text(json.dumps(orig_session)) r = http( @@ -235,10 +237,8 @@ class TestExpiredCookies: assert 'to_stay' in updated_session['cookies'] assert 'to_expire' not in updated_session['cookies'] - shutil.rmtree(config_dir) - @pytest.mark.parametrize( - argnames=['raw_header', 'timestamp', 'expected'], + argnames=['headers', 'now', 'expected_expired'], argvalues=[ ( [ @@ -271,11 +271,9 @@ class TestExpiredCookies: ('Connection', 'keep-alive') ], datetime(2020, 6, 11).timestamp(), - [ - - ] + [] ) ] ) - def test_get_expired_cookies_manages_multiple_cookie_headers(self, raw_header, timestamp, expected): - assert get_expired_cookies(raw_header, curr_timestamp=timestamp) == expected + def test_get_expired_cookies_manages_multiple_cookie_headers(self, headers, now, expected_expired): + assert get_expired_cookies(headers, now=now) == expected_expired