-
-
Notifications
You must be signed in to change notification settings - Fork 831
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
How to correctly save and load cookies? #895
Comments
From what I can see this might be a bug in the handling of the Can you provide a repro example that completely drops the pickling logic? That is, pass the contents of your pickled file as a plain dict literal and see if you can iterate over client.cookies. |
|
Okay, thanks for the code example. From my perspective the You're trying to reuse an old set of cookies from a previous session, but Google forcibly sends you a fresh pair for this new session, so you end up with multiple versions of the I assume most cookies are session-sensitive like this, so I'm not even sure in what context your initial use case of reusing cookies from a pickle file would be valid. But in any case, if that's what you want to do then I'd recommend making sure you remove any session-sensitive cookies from a cookies dict before reusing it on a new client. (Which cookies are session-sensitive depends on the server you're talking to.) Going to close this for now, as behavior seems legit on HTTPX side… Thanks! |
Problem is that importing cookies from dict sets domain to empty string and website is setting cookies with domain so we end up with two cookies with exactly the same key valid for that domain. Sure it is not httpx issue but user who didn't set correct domain when importing cookies but it might generate few hard to understand problems for a lot of people. For example if we load website that sets up cookie and then use cookies.update we end up with two cookies with the same key and httpx is going to use "old" value with correct domain. >>> r = httpx.Client()
>>> r.get('https://httpbin.org/cookies/set/key/value')
<Response [200 OK]>
>>> r.cookies.jar # we've got one cookie key=value2
<CookieJar[Cookie(version=0, name='key', value='value', port=None, port_specified=False, domain='httpbin.org', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={}, rfc2109=False)]>
>>> r.cookies.update({'key': 'value2'})
>>> r.cookies.jar # two cookies with the same key
<CookieJar[Cookie(version=0, name='key', value='value2', port=None, port_specified=False, domain='', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='key', value='value', port=None, port_specified=False, domain='httpbin.org', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={}, rfc2109=False)]>
>>> r.get('https://httpbin.org/cookies').text # "old" cookie with set up domain is used
'{\n "cookies": {\n "key": "value"\n }\n}\n' Perfect solution would be more complex update/load and dump/save method that handles domain, path and other cookie params for us but we can also allow easly setting somekind of policy that doesn't allow existance of two cookies with same key that are valid for any domain. Anyway we should at least warn user in docs about this behaviour. |
Cookies are domain-sensitive, so I think our current behavior on Besides, the Cookies docs advocate for using But I'm not actually sure that's what you need for your dump/load use case. I think you can get away with pickling the Code example: import pickle
import httpx
def save_cookies(client):
with open("cookies.pk", "wb") as f:
pickle.dump(client.cookies.jar, f)
def load_cookies():
if not os.path.isfile("cookies.pk"):
return None
with open("cookies.pk", "rb") as f:
return pickle.load(f)
client = httpx.Client(cookies=load_cookies())
save_cookies(client) |
Sure, this is correct behaviour, not complaing at, I'm just saying that it might be surprising. I think if user loads cookies without domain (may i say domain insensitive?), he's probably using this httpx session only on one website (at least he should be), so if this website wants to change cookie value there is no chance but creation of new one. We end up with duplicates that breaks simplicity of managing cookiejar as dict - CookieConflict starts to pop out but user probably never wanted this to happen, he wanted simple, easy and "human" behaviour without duplicates. |
def save_cookies(self):
with open("cookies.pk", "wb") as f:
pickle.dump(self.client.cookies.jar._cookies, f)
def load_cookies(self):
if not os.path.isfile("cookies.pk"):
return None
cookies = httpx.Cookies()
with open("cookies.pk", "rb") as f:
jar_cookies = pickle.load(f)
for domain , pc in jar_cookies.items():
for path, c in pc.items():
for k, v in c.items():
cookies.set(k, v.value, domain=domain, path=path)
return cookies |
The proposed solution sadly does not work because the |
I've solved this by pickling Client.cookies.jar._cookies to save the cookies, then loading them in by using Client.cookies.jar._cookies.update(loaded_cookies). I use Client.cookies.jar.clear_expired_cookies() afterward to make sure i don't have stale cookies afterward. |
Question
I can only load cookies once and then it will occur CookieConflict Excpetion.
Could you please tell me how to correctly load and save cookies?
Will cause CookieConflict error
And i check the cookies keys()
The text was updated successfully, but these errors were encountered: