Skip to content

Add Cookies recipe - #155

Merged
mre merged 6 commits into
masterfrom
docs-cookie-format
Jun 7, 2026
Merged

Add Cookies recipe#155
mre merged 6 commits into
masterfrom
docs-cookie-format

Conversation

@mre

@mre mre commented May 30, 2026

Copy link
Copy Markdown
Member

Adds a short recipe page documenting the --cookie-jar option and the JSON format of the cookie jar file.

Fixes lycheeverse/lychee#1851
Related to lycheeverse/lychee#2215.

Comment thread src/content/docs/recipes/cookies.md Outdated

@katrinafyi katrinafyi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks good. Just wondering if there's a citation for this format somewhere upstream?

Also, the raw_cookie field seems to repeat information which is also in separate fields. Maybe that's just what it is, but it's a bit odd.

@mre

mre commented Jun 7, 2026

Copy link
Copy Markdown
Member Author

Thanks for all the review. I tried my best to fill in the gaps now.

And yes, it feels like there's some redundancy in the format, but that's a limitation of the crate we're using. At least from their source code, I currently can't see any better way to pass the data to cookie_store.

lychee has essentially zero control here. lychee-lib/src/types/cookies.rs just wires up:

  • reqwest_cookie_store::CookieStoreMutex for the live store
  • cookie_store::serde::json::{load, save} for persistence

So the on-disk format is entirely cookie_store::Cookie's #[derive(Serialize)]. This is the same one reqwest_cookie_store's own docs steer us toward. To change the format we'd have to stop using cookie_store's serde and own a custom representation. 😕

And come to think of it, the fields aren't truly redundant. raw_cookie is the literal header, while the parsed fields path, domain, and expires are its resolved RFC 6265 state relative to the originating request.

The three parsed fields capture state that the raw Set-Cookie header can't, because they were resolved against the request the cookie came from:

  • expires: Max-Age is relative to when the cookie was received. try_from_raw_cookie resolves it to an absolute AtUtc timestamp. If only raw_cookie were stored, a Max-Age=3600 cookie would re-evaluate to "now" on every reload. At least that's what I understand when reading the note on From<Cookie> for RawCookie: // Max-Age is relative, will not have same meaning now, so only set Expires.

  • domain: HostOnly vs Suffix is RFC 6265's host-only flag, derived from the request URL via CookieDomain::host_only(request_url). A Set-Cookie without a Domain= attribute doesn't record which host it's bound to.

  • path: the boolean in ["/foo", false] is is_from_path_attr — whether the path came from a Path= attribute or was defaulted from the request URL. The default path is computed from the request URI, which the header doesn't contain.

So the parsed fields serve a slightly different purpose (provenance?). I was thinking about adding a note to the docs, but I decided that most people won't care and that it could be too much information and get confusing. But great observation!

@mre

mre commented Jun 7, 2026

Copy link
Copy Markdown
Member Author

Guess all comments have been addressed for now (thanks!). Merging.

@mre
mre merged commit 0efed82 into master Jun 7, 2026
2 checks passed
@mre
mre deleted the docs-cookie-format branch June 7, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add info to the docs about cookie format for the --cookie-jar flag

3 participants