mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #34709 -- Raised BadRequest for non-UTF-8 requests with the application/x-www-form-urlencoded content type.
Thanks Eki Xu for the report.
This commit is contained in:
parent
9c37103a98
commit
11920e7795
@ -7,6 +7,7 @@ from urllib.parse import parse_qsl, quote, urlencode, urljoin, urlsplit
|
||||
from django.conf import settings
|
||||
from django.core import signing
|
||||
from django.core.exceptions import (
|
||||
BadRequest,
|
||||
DisallowedHost,
|
||||
ImproperlyConfigured,
|
||||
RequestDataTooBig,
|
||||
@ -377,10 +378,16 @@ class HttpRequest:
|
||||
self._mark_post_parse_error()
|
||||
raise
|
||||
elif self.content_type == "application/x-www-form-urlencoded":
|
||||
self._post, self._files = (
|
||||
QueryDict(self.body, encoding=self._encoding),
|
||||
MultiValueDict(),
|
||||
)
|
||||
# According to RFC 1866, the "application/x-www-form-urlencoded"
|
||||
# content type does not have a charset and should be always treated
|
||||
# as UTF-8.
|
||||
if self._encoding is not None and self._encoding.lower() != "utf-8":
|
||||
raise BadRequest(
|
||||
"HTTP requests with the 'application/x-www-form-urlencoded' "
|
||||
"content type must be UTF-8 encoded."
|
||||
)
|
||||
self._post = QueryDict(self.body, encoding="utf-8")
|
||||
self._files = MultiValueDict()
|
||||
else:
|
||||
self._post, self._files = (
|
||||
QueryDict(encoding=self._encoding),
|
||||
|
@ -580,6 +580,10 @@ Miscellaneous
|
||||
* Executing SQL queries before the app registry has been fully populated now
|
||||
raises :exc:`RuntimeWarning`.
|
||||
|
||||
* :exc:`~django.core.exceptions.BadRequest` is raised for non-UTF-8 encoded
|
||||
requests with the :mimetype:`application/x-www-form-urlencoded` content type.
|
||||
See :rfc:`1866` for more details.
|
||||
|
||||
.. _deprecated-features-5.0:
|
||||
|
||||
Features deprecated in 5.0
|
||||
|
@ -3,7 +3,7 @@ from io import BytesIO
|
||||
from itertools import chain
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.core.exceptions import DisallowedHost
|
||||
from django.core.exceptions import BadRequest, DisallowedHost
|
||||
from django.core.handlers.wsgi import LimitedStream, WSGIRequest
|
||||
from django.http import (
|
||||
HttpHeaders,
|
||||
@ -369,10 +369,7 @@ class RequestsTests(SimpleTestCase):
|
||||
)
|
||||
self.assertEqual(request.POST, {"key": ["España"]})
|
||||
|
||||
def test_alternate_charset_POST(self):
|
||||
"""
|
||||
Test a POST with non-utf-8 payload encoding.
|
||||
"""
|
||||
def test_non_utf8_charset_POST_bad_request(self):
|
||||
payload = FakePayload(urlencode({"key": "España".encode("latin-1")}))
|
||||
request = WSGIRequest(
|
||||
{
|
||||
@ -382,7 +379,30 @@ class RequestsTests(SimpleTestCase):
|
||||
"wsgi.input": payload,
|
||||
}
|
||||
)
|
||||
self.assertEqual(request.POST, {"key": ["España"]})
|
||||
msg = (
|
||||
"HTTP requests with the 'application/x-www-form-urlencoded' content type "
|
||||
"must be UTF-8 encoded."
|
||||
)
|
||||
with self.assertRaisesMessage(BadRequest, msg):
|
||||
request.POST
|
||||
with self.assertRaisesMessage(BadRequest, msg):
|
||||
request.FILES
|
||||
|
||||
def test_utf8_charset_POST(self):
|
||||
for charset in ["utf-8", "UTF-8"]:
|
||||
with self.subTest(charset=charset):
|
||||
payload = FakePayload(urlencode({"key": "España"}))
|
||||
request = WSGIRequest(
|
||||
{
|
||||
"REQUEST_METHOD": "POST",
|
||||
"CONTENT_LENGTH": len(payload),
|
||||
"CONTENT_TYPE": (
|
||||
f"application/x-www-form-urlencoded; charset={charset}"
|
||||
),
|
||||
"wsgi.input": payload,
|
||||
}
|
||||
)
|
||||
self.assertEqual(request.POST, {"key": ["España"]})
|
||||
|
||||
def test_body_after_POST_multipart_form_data(self):
|
||||
"""
|
||||
@ -694,18 +714,31 @@ class RequestsTests(SimpleTestCase):
|
||||
request.body
|
||||
|
||||
def test_set_encoding_clears_POST(self):
|
||||
payload = FakePayload("name=Hello Günter")
|
||||
payload = FakePayload(
|
||||
"\r\n".join(
|
||||
[
|
||||
f"--{BOUNDARY}",
|
||||
'Content-Disposition: form-data; name="name"',
|
||||
"",
|
||||
"Hello Günter",
|
||||
f"--{BOUNDARY}--",
|
||||
"",
|
||||
]
|
||||
)
|
||||
)
|
||||
request = WSGIRequest(
|
||||
{
|
||||
"REQUEST_METHOD": "POST",
|
||||
"CONTENT_TYPE": "application/x-www-form-urlencoded",
|
||||
"CONTENT_TYPE": MULTIPART_CONTENT,
|
||||
"CONTENT_LENGTH": len(payload),
|
||||
"wsgi.input": payload,
|
||||
}
|
||||
)
|
||||
self.assertEqual(request.POST, {"name": ["Hello Günter"]})
|
||||
request.encoding = "iso-8859-16"
|
||||
self.assertEqual(request.POST, {"name": ["Hello GĂŒnter"]})
|
||||
# FIXME: POST should be accessible after changing the encoding
|
||||
# (refs #14035).
|
||||
# self.assertEqual(request.POST, {"name": ["Hello GĂŒnter"]})
|
||||
|
||||
def test_set_encoding_clears_GET(self):
|
||||
payload = FakePayload("")
|
||||
|
Loading…
Reference in New Issue
Block a user