summaryrefslogtreecommitdiff
path: root/tests/utils_tests/test_http.py
diff options
context:
space:
mode:
authorKhudyakov Artem <khudyak.artem@gmail.com>2024-07-29 22:05:10 +0300
committernessita <124304+nessita@users.noreply.github.com>2025-03-27 08:57:03 -0300
commit9aabe7eae3eeb3e64c5a0f3687118cd806158550 (patch)
treebbc7cc8752b20fe850bc890d86e9df07b9d4958d /tests/utils_tests/test_http.py
parent0d92428d77fafff373e05dd5a6cdb62bd1dfbda0 (diff)
Fixed #35440 -- Simplified parse_header_parameters by leveraging stdlid's Message.
The `parse_header_parameters` function historically used Python's `cgi` module (now deprecated). In 34e2148fc725e7200050f74130d7523e3cd8507a, the logic was inlined to work around this deprecation ( #33173). Later, in d4d5427571b4bf3a21c902276c2a00215c2a37cc, the header parsing logic was further cleaned up to align with `multipartparser.py` (#33697). This change takes it a step further by replacing the copied `cgi` logic with Python's `email.message.Message` API for a more robust and maintainable header parsing implementation. Thanks to Raphael Gaschignard for testing, and to Adam Johnson and Shai Berger for reviews. Co-authored-by: Ben Cail <bcail@crossway.org> Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
Diffstat (limited to 'tests/utils_tests/test_http.py')
-rw-r--r--tests/utils_tests/test_http.py45
1 files changed, 44 insertions, 1 deletions
diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py
index d18fb63c0c..3730c2fcf5 100644
--- a/tests/utils_tests/test_http.py
+++ b/tests/utils_tests/test_http.py
@@ -6,6 +6,7 @@ from unittest import mock
from django.test import SimpleTestCase
from django.utils.datastructures import MultiValueDict
from django.utils.http import (
+ MAX_HEADER_LENGTH,
base36_to_int,
content_disposition_header,
escape_leading_slashes,
@@ -424,6 +425,8 @@ class EscapeLeadingSlashesTests(unittest.TestCase):
class ParseHeaderParameterTests(unittest.TestCase):
def test_basic(self):
tests = [
+ ("", ("", {})),
+ (None, ("none", {})),
("text/plain", ("text/plain", {})),
("text/vnd.just.made.this.up ; ", ("text/vnd.just.made.this.up", {})),
("text/plain;charset=us-ascii", ("text/plain", {"charset": "us-ascii"})),
@@ -448,9 +451,17 @@ class ParseHeaderParameterTests(unittest.TestCase):
("attachment", {"filename": "strange;name", "size": "123"}),
),
(
+ 'attachment; filename="strange;name";;;;size=123;;;',
+ ("attachment", {"filename": "strange;name", "size": "123"}),
+ ),
+ (
'form-data; name="files"; filename="fo\\"o;bar"',
("form-data", {"name": "files", "filename": 'fo"o;bar'}),
),
+ (
+ 'form-data; name="files"; filename="\\"fo\\"o;b\\\\ar\\""',
+ ("form-data", {"name": "files", "filename": '"fo"o;b\\ar"'}),
+ ),
]
for header, expected in tests:
with self.subTest(header=header):
@@ -480,12 +491,13 @@ class ParseHeaderParameterTests(unittest.TestCase):
"""
Test wrongly formatted RFC 2231 headers (missing double single quotes).
Parsing should not crash (#24209).
+ But stdlib email still decodes (#35440).
"""
test_data = (
(
"Content-Type: application/x-stuff; "
"title*='This%20is%20%2A%2A%2Afun%2A%2A%2A",
- "'This%20is%20%2A%2A%2Afun%2A%2A%2A",
+ "'This is ***fun***",
),
("Content-Type: application/x-stuff; title*='foo.html", "'foo.html"),
("Content-Type: application/x-stuff; title*=bar.html", "bar.html"),
@@ -494,6 +506,37 @@ class ParseHeaderParameterTests(unittest.TestCase):
parsed = parse_header_parameters(raw_line)
self.assertEqual(parsed[1]["title"], expected_title)
+ def test_header_max_length(self):
+ base_header = "Content-Type: application/x-stuff; title*="
+ base_header_len = len(base_header)
+
+ test_data = [
+ (MAX_HEADER_LENGTH, {}),
+ (MAX_HEADER_LENGTH, {"max_length": None}),
+ (MAX_HEADER_LENGTH + 1, {"max_length": None}),
+ (100, {"max_length": 100}),
+ ]
+ for line_length, kwargs in test_data:
+ with self.subTest(line_length=line_length, kwargs=kwargs):
+ title = "x" * (line_length - base_header_len)
+ line = base_header + title
+ assert len(line) == line_length
+
+ parsed = parse_header_parameters(line, **kwargs)
+
+ expected = ("content-type: application/x-stuff", {"title": title})
+ self.assertEqual(parsed, expected)
+
+ def test_header_too_long(self):
+ test_data = [
+ ("x" * (MAX_HEADER_LENGTH + 1), {}),
+ ("x" * 101, {"max_length": 100}),
+ ]
+ for line, kwargs in test_data:
+ with self.subTest(line_length=len(line), kwargs=kwargs):
+ with self.assertRaises(ValueError):
+ parse_header_parameters(line, **kwargs)
+
class ContentDispositionHeaderTests(unittest.TestCase):
def test_basic(self):