Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CookieJar filter_cookies does not preserve expiration date #3951

Open
bwright1558 opened this issue Jul 30, 2019 · 4 comments
Open

CookieJar filter_cookies does not preserve expiration date #3951

bwright1558 opened this issue Jul 30, 2019 · 4 comments

Comments

@bwright1558
Copy link

Long story short

Using CookieJar.filter_cookies() does not preserve the expiration date of the returned cookies.

Expected behaviour

Return the full cookie Morsels that have the expires, domain, path, etc. fields.

Actual behaviour

The expires field is not included in the cookie Morsels returned from CookieJar.filter_cookies().

Steps to reproduce

Here's a full working example to demonstrate. It's a contrived example, but it gets the point across. Iterating through cookie_jar gives me the full Morsel objects with expiration. But iterating through filtered_cookies does not contain the expiration.

from http.cookies import SimpleCookie

import yarl
from aiohttp import CookieJar


cookies = SimpleCookie()
cookies.load('browser_session=secret; Domain=.test.com; Path=/; Expires=Tue, 30-Jul-69 14:47:41 GMT; HttpOnly')

cookie_jar = CookieJar()
cookie_jar.update_cookies(cookies)

for cookie in cookie_jar:
    print(f'{cookie.value!r} expires {cookie["expires"]!r}')

url = yarl.URL('http://www.test.com')
filtered_cookies = cookie_jar.filter_cookies(url)
for _, cookie in filtered_cookies.items():
    print(f'{cookie.value!r} expires {cookie["expires"]!r}')

Your environment

I'm using the latest stable release of aiohttp (3.5.4).

@asvetlov
Copy link
Member

asvetlov commented Aug 1, 2019

expire makes sense for server-side Set-Cookie header.
filter_cookies() returns a data for generating client-side Cookie header. This header doesn't contain an expiration attribute: if the cookie is expired it is not sent to the server at all.
Why do you want this attribute in filter_cookies() result?

@bwright1558
Copy link
Author

filter_cookies() may be the wrong way for me to go, but I'll describe what I am ultimately trying to do. I am automating signing into a website. Eventually, my session will expire and the program will have to sign in again. I figure I can use the expires value from the website's cookies to estimate when my program needs to sign back into the website.

@asvetlov
Copy link
Member

asvetlov commented Aug 2, 2019

Do you have an idea of how the desired API should look like?
How other libraries solve your problem?

@bwright1558
Copy link
Author

Below is more or less how I expect filter_cookies to work. Why does filter_cookies not just return the original Morsels (or a full copy of the originals)?

def filter_cookies(self, request_url: URL=URL()) -> 'BaseCookie[str]':
    """Returns this jar's cookies filtered by their attributes."""
    self._do_expiration()
    if not isinstance(request_url, URL):
        warnings.warn("The method accepts yarl.URL instances only, got {}"
                        .format(type(request_url)),
                        DeprecationWarning)
        request_url = URL(request_url)
    filtered = SimpleCookie()
    hostname = request_url.raw_host or ""
    is_not_secure = request_url.scheme not in ("https", "wss")

    for cookie in self:
        name = cookie.key
        domain = cookie["domain"]

        # Send shared cookies
        if not domain:
            # Assign original Morsel (or a full copy) to `filtered[name]`.
            filtered[name] = cookie
            continue

        if not self._unsafe and is_ip_address(hostname):
            continue

        if (domain, name) in self._host_only_cookies:
            if domain != hostname:
                continue
        elif not self._is_domain_match(domain, hostname):
            continue

        if not self._is_path_match(request_url.path, cookie["path"]):
            continue

        if is_not_secure and cookie["secure"]:
            continue
        
        # Assign original Morsel (or a full copy) to `filtered[name]`.
        filtered[name] = cookie

    return filtered

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants