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.
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";", sosessionidis 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
Environment: Zappa 0.62.1 (still present on
master), API Gateway REST API (payload v1), Django 5.x, Chrome 150.Suggested fix
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.