Skip to content

Preserve expiration instants for timezone-aware cookies - #337

Open
HuaTNA wants to merge 2 commits into
lundberg:masterfrom
HuaTNA:fix-cookie-expiry-timezone
Open

HuaTNA wants to merge 2 commits into
lundberg:masterfrom
HuaTNA:fix-cookie-expiry-timezone

Conversation

@HuaTNA

@HuaTNA HuaTNA commented Oct 29, 2026 •

Copy link
Copy Markdown

SetCookie(expires=...) formats non-UTC datetimes with their local wall-clock fields followed by GMT, shifting the expiration instant. A future cookie can consequently appear expired to HTTPX.

Convert aware datetimes to UTC before formatting. The focused parameterized regression covers both offset directions (including a half-hour offset), a year boundary, and the existing naive-datetime/string behavior; the existing all-attributes test covers UTC.

Fixes #336.

Review follow-up: adds one public respx.mock / respond(cookies=...) / httpx.Client regression asserting the stored cookie-jar expiration matches the aware datetime's epoch. It fails against the original implementation and passes with this fix.

Validation on macOS:

  • Regression before the fix: 2 failed, 3 passed; after the fix: 5 passed.
  • nox -s test-3.11: 326 passed, 2 remote pass-through tests skipped, 100% configured statement/branch coverage (Python 3.11.15).
  • Project mypy session on Python 3.10 and all pinned pre-commit hooks passed.
  • Local public respx.mock / respond(cookies=...) / HTTPX 0.28.1 client checks confirm identical cookie-jar expiry timestamps for UTC and both offset directions. Additional local controls cover Toronto DST folds and a naive-like tzinfo.

AI assistance was used for code inspection, implementation, and local test execution. The issue was found through code analysis and reproduction, not a production incident.

@Pavel-Shcherbo Pavel-Shcherbo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed commit 0d0984e on CPython 3.14.6 with HTTPX 0.28.1.

tests/test_utils.py --no-cov: 5 passed. I also checked the cookie jar through respx.mock / respond(cookies=...) / httpx.Client: UTC offsets -12:00, -05:00, -03:30, +00:00, +05:30 and +14:00, plus both Toronto DST folds on 2030-11-03. All eight retain int(expires.timestamp()) at this head; seven fail against the base implementation. Three further controls preserve naive datetime, naive-like tzinfo (utcoffset() is None) and string behavior.

The utcoffset() guard handles awareness correctly without converting naive-like values through the machine's local timezone. I found no blocking issue in this diff.

One optional follow-up: retain a public-API cookie-jar assertion in the project suite, alongside the formatting test. That would directly cover the expiration behavior users observe. This review covers the cookie change and focused controls; I have not run the full RESPX compatibility matrix.

@HuaTNA

HuaTNA commented Nov 5, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed review. Added a focused public-API regression in 2ea43a1: a response configured with SetCookie(expires=...) passes through respx.mock, respond(cookies=...) and httpx.Client, then asserts the stored cookie-jar expiry equals int(expires.timestamp()).

It fails against the original implementation (a 5h30m shift) and passes with the fix. The documented Python 3.11 nox session now has 326 passing tests, 2 remote pass-through skips and 100% configured statement/branch coverage; pinned hooks and mypy pass. I have not run the full compatibility matrix.

@Pavel-Shcherbo

Copy link
Copy Markdown

Independently checked 2ea43a1 on Python 3.12.9 / HTTPX 0.28.1: the new public-API regression plus tests/test_utils.py pass (6 tests). Restoring only the original SetCookie implementation makes the unchanged new regression fail: the cookie jar stores 4102464600 instead of 4102444800, a 19,800-second shift. This covers the end-user behavior I suggested retaining. Thanks for adding it.

This follow-up is limited to those synchronous checks; I have not independently verified the full compatibility matrix or coverage result.

This branch has not been deployed

No deployments
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.

SetCookie shifts expiration timestamps for non-UTC datetimes

2 participants