feat(sessions): add setCookies() to restore an exported cookie jar - #202
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #201
Problem
getAllCookies()returns cookies with full metadata, but there's no way to put them back.setCookie(name, value, url)only takes a name/value pair, so domain, path, secure, httpOnly, sameSite and expiry are all lost on re-import. That makes a jar export/import round-trip impossible, which is what you need to persist a logged-in session across process restarts.Changes
session.setCookies(cookies, url?)takes the output ofgetAllCookies()directly:Each cookie is built with
cookie::CookieBuilderrather than by formatting aSet-Cookiestring, so a value containing;stays verbatim instead of being reparsed as attributes. The whole batch is validated before anything is stored, so a rejected cookie leaves the jar untouched rather than applying half a restore. Cookies already pastexpiresAtMsare dropped, matching how the jar treats an expiredSet-Cookie.The
urlscopes host-only cookies, the ones with noDomainof their own. wreq's jar keeps their origin host as an internal key and doesn't return it fromget_all(), so it's absent from the export and has to be supplied. A jar holding host-only cookies from several hosts therefore can't be restored from oneurl;SessionCookieInitalso accepts a per-cookieurlfor that case. Upstream fix proposed in 0x676e67/wreq#1269, which would let the export carry the host and make both arguments unnecessary.Two other fixes came out of this:
getAllCookies()now reportssameSite: "none". wreq'sCookiewrapper only exposessame_site_lax()/same_site_strict(), soSameSite=Nonewas indistinguishable from an absent attribute and exported asundefined. Real servers use it: upwork.com sends it on__cf_bm,__cflbandAWSALBTGCORS. The export now reads the attribute off the raw cookie.expiresAtMsno longer drifts by a millisecond per round-trip. Epoch nanoseconds exceed f64's exact integer range, soms * 1e6lost precision; whole and fractional milliseconds are now scaled separately.Tests
Five added to
src/test/http/sessions.spec.ts: attribute-preserving restore through a JSON round-trip plus a live request, per-cookie scoping across two hosts, rejected-batch atomicity, expired-cookie drop, everySameSitevalue, andsetCookieson a disposed session. 199 pass.Checked against tough-cookie 6.0.2 as an oracle: 15
Set-Cookieshapes compared field by field, includingSameSite=None, lowercasesamesite=none, uppercaseSAMESITE=STRICTand an invalidSameSite=Bogus, plus cookie selection across 6 URLs covering Secure filtering, path matching, domain matching and host-only scoping. All agree.Also verified against real sites: a 17-cookie jar spanning httpbingo.org, google.com, github.com and upwork.com round-trips byte-identical, restored
__cf_bmis accepted by Cloudflare (200 on patreon.com, openai.com, upwork.com), and a jar written to disk in one process restores in another with the origin server seeing identical cookies.Docs
docs/api-reference/sessions.mdxanddocs/concepts/sessions.mdx.