Skip to content

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

Description

@kimgunnn

Bug

merge_headers() joins every multi-value header with ", ":

https://github.com/zappa/Zappa/blob/master/zappa/utilities.py#L965-L966

That's fine for most headers, but cookies are separated by "; ", not commas.

HTTP/2 clients (Chrome, for one) may send the cookie header as multiple field lines,
which API Gateway payload v1 delivers as a list in multiValueHeaders["cookie"].
Zappa then reassembles them as csrftoken=A, sessionid=B — Django only splits cookies on ";", so sessionid is silently dropped and the user becomes anonymous.
The result is a login redirect loop that's hard to debug, since browser DevTools still shows one well-formed Cookie: line.

Reproduction

from zappa.utilities import merge_headers

event = {
    "headers": {"cookie": "csrftoken=AAAA"},
    "multiValueHeaders": {"cookie": ["csrftoken=AAAA", "sessionid=BBBB"]},
}
merge_headers(event)
# actual:   {'cookie': 'csrftoken=AAAA, sessionid=BBBB'}
# expected: {'cookie': 'csrftoken=AAAA; sessionid=BBBB'}

Environment: Zappa 0.62.1 (still present on master), API Gateway REST API (payload v1), Django 5.x, Chrome 150.

Suggested fix

for h in multi_headers.keys():
    separator = "; " if h.lower() == "cookie" else ", "
    multi_headers[h] = separator.join(multi_headers[h])

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

Happy to open a PR with the fix and a regression test.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions