From f2a6c0477fd95518ffb4fcea8e655a9062874bd2 Mon Sep 17 00:00:00 2001 From: SaJH Date: Wed, 20 Aug 2025 22:54:46 +0900 Subject: [PATCH] Fixed #36399 -- Added support for multiple Cookie headers in HTTP/2 for ASGIRequest. Signed-off-by: SaJH --- django/core/handlers/asgi.py | 6 +++++- docs/releases/6.0.txt | 3 ++- tests/asgi/tests.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/django/core/handlers/asgi.py b/django/core/handlers/asgi.py index beace7597c..b4056ca042 100644 --- a/django/core/handlers/asgi.py +++ b/django/core/handlers/asgi.py @@ -94,7 +94,11 @@ class ASGIRequest(HttpRequest): # HTTP/2 say only ASCII chars are allowed in headers, but decode # latin1 just in case. value = value.decode("latin1") - if corrected_name in self.META: + if corrected_name == "HTTP_COOKIE": + value = value.rstrip("; ") + if "HTTP_COOKIE" in self.META: + value = self.META[corrected_name] + "; " + value + elif corrected_name in self.META: value = self.META[corrected_name] + "," + value self.META[corrected_name] = value # Pull out request encoding, if provided. diff --git a/docs/releases/6.0.txt b/docs/releases/6.0.txt index 3e250706ec..e54b9788ce 100644 --- a/docs/releases/6.0.txt +++ b/docs/releases/6.0.txt @@ -333,7 +333,8 @@ Pagination Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~ -* ... +* Multiple ``Cookie`` headers are now supported for HTTP/2 requests when + running with ASGI. Security ~~~~~~~~ diff --git a/tests/asgi/tests.py b/tests/asgi/tests.py index d3cc09cc50..bb1020dd47 100644 --- a/tests/asgi/tests.py +++ b/tests/asgi/tests.py @@ -732,3 +732,34 @@ class ASGITest(SimpleTestCase): await handler.read_body(receive_rolled) # The second write should have rolled over to disk. self.assertTrue(any(t != loop_thread for t in called_threads)) + + def test_multiple_cookie_headers_http2(self): + test_cases = [ + { + "label": "RFC-compliant headers (no semicolon)", + "headers": [ + (b"cookie", b"a=abc"), + (b"cookie", b"b=def"), + (b"cookie", b"c=ghi"), + ], + }, + { + # Some clients may send cookies with trailing semicolons. + "label": "Headers with trailing semicolons", + "headers": [ + (b"cookie", b"a=abc;"), + (b"cookie", b"b=def;"), + (b"cookie", b"c=ghi;"), + ], + }, + ] + + for case in test_cases: + with self.subTest(case["label"]): + scope = self.async_request_factory._base_scope( + path="/", http_version="2.0" + ) + scope["headers"] = case["headers"] + request = ASGIRequest(scope, None) + self.assertEqual(request.META["HTTP_COOKIE"], "a=abc; b=def; c=ghi") + self.assertEqual(request.COOKIES, {"a": "abc", "b": "def", "c": "ghi"})