Skip to content

Fix merge_headers() joining multiple Cookie headers with ", " - #1467

Open
kimgunnn wants to merge 3 commits into
zappa:masterfrom
kimgunnn:fix/cookie-header-merge
Open

Fix merge_headers() joining multiple Cookie headers with ", "#1467
kimgunnn wants to merge 3 commits into
zappa:masterfrom
kimgunnn:fix/cookie-header-merge

Conversation

@kimgunnn

@kimgunnn kimgunnn commented Jul 20, 2026

Copy link
Copy Markdown

Description

Fixes #1466

merge_headers() joins all multi-value headers with ", ",
including Cookie — but cookies are separated by "; ", not commas.
HTTP/2 clients such as Chrome may split the cookie header into multiple field lines,
which API Gateway payload v1 delivers via multiValueHeaders.
Zappa then reassembles them as csrftoken=A, sessionid=B,
which WSGI frameworks cannot parse — sessionid is silently dropped and session auth breaks (e.g. Django login loops).

The payload v2 path already joins event["cookies"] with "; "
(zappa/wsgi.py), so this change brings v1 in line with v2.

GitHub Issues

#1466

Cookies are separated by "; ", not commas. HTTP/2 clients may split
the cookie header into multiple field lines, and joining them back
with ", " produces a Cookie header that WSGI frameworks cannot parse,
which breaks session authentication (e.g. Django login loops).

The payload v2 path already joins event["cookies"] with "; "; this
brings the v1 path in line.

Fixes zappa#1466
@kimgunnn
kimgunnn force-pushed the fix/cookie-header-merge branch from 6af9421 to 74b9e12 Compare July 21, 2026 01:08

@monkut monkut left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The fix itself is correct and verified.
Requesting a few small changes to align with project conventions before merge:

  1. Add a lowercase cookie test case. The new test uses "Cookie", but the real-world HTTP/2 shape (and the reproduction in #1466) is lowercase "cookie" — which is exactly what the h.lower() branch exists to handle, and it's currently untested. A second assertion or a parametrized case with {"multiValueHeaders": {"cookie": [...]}} would cover it.

Optional, non-blocking: the existing merge_headers tests live in tests/test_handler.py (test_merge_headers_no_multi_value etc.). Since the function lives in zappa/utilities.py, the new tests' placement in tests/test_utilities.py is reasonable — but consider moving the old ones alongside them in a follow-up so coverage of the function isn't split across two files.

@coveralls

coveralls commented Jul 29, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 74.75% (-0.04%) from 74.785% — kimgunnn:fix/cookie-header-merge into zappa:master

@kimgunnn

Copy link
Copy Markdown
Author

Good catch — added the lowercase case via subTest so both spellings are covered. Re: consolidating the existing merge_headers tests from test_handler.py, happy to do that in a follow-up PR.

@kimgunnn
kimgunnn requested a review from monkut July 29, 2026 12:55
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.

merge_headers() joins multiple Cookie headers with ", " instead of "; ", breaking Django sessions over HTTP/2

3 participants