mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
Added FormParser and MultiPartParser
This commit is contained in:
parent
9e7ac58901
commit
caab50bb85
53
django/http/parsers.py
Normal file
53
django/http/parsers.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
from django.core.exceptions import BadRequest
|
||||||
|
from django.http.multipartparser import MultiPartParser as _MultiPartParser
|
||||||
|
from django.utils.datastructures import ImmutableList, MultiValueDict
|
||||||
|
|
||||||
|
|
||||||
|
class BaseParser:
|
||||||
|
media_type = None
|
||||||
|
|
||||||
|
def parse(self, request):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FormParser(BaseParser):
|
||||||
|
media_type = "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
def parse(self, request):
|
||||||
|
from django.http import QueryDict
|
||||||
|
|
||||||
|
# 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 request._encoding is not None and request._encoding.lower() != "utf-8":
|
||||||
|
raise BadRequest(
|
||||||
|
"HTTP requests with the 'application/x-www-form-urlencoded' "
|
||||||
|
"content type must be UTF-8 encoded."
|
||||||
|
)
|
||||||
|
return QueryDict(request.body, encoding="utf-8"), MultiValueDict()
|
||||||
|
|
||||||
|
|
||||||
|
class MultiPartParser(BaseParser):
|
||||||
|
media_type = "multipart/form-data"
|
||||||
|
|
||||||
|
def parse(self, request):
|
||||||
|
if hasattr(request, "_body"):
|
||||||
|
# Use already read data
|
||||||
|
data = BytesIO(request._body)
|
||||||
|
else:
|
||||||
|
data = request
|
||||||
|
|
||||||
|
request.upload_handlers = ImmutableList(
|
||||||
|
request.upload_handlers,
|
||||||
|
warning=(
|
||||||
|
"You cannot alter upload handlers after the upload has been "
|
||||||
|
"processed."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
parser = _MultiPartParser(
|
||||||
|
request.META, data, request.upload_handlers, request.encoding
|
||||||
|
)
|
||||||
|
_post, _files = parser.parse()
|
||||||
|
return _post, _files
|
@ -7,18 +7,14 @@ from urllib.parse import parse_qsl, quote, urlencode, urljoin, urlsplit
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.core.exceptions import (
|
from django.core.exceptions import (
|
||||||
BadRequest,
|
|
||||||
DisallowedHost,
|
DisallowedHost,
|
||||||
ImproperlyConfigured,
|
ImproperlyConfigured,
|
||||||
RequestDataTooBig,
|
RequestDataTooBig,
|
||||||
TooManyFieldsSent,
|
TooManyFieldsSent,
|
||||||
)
|
)
|
||||||
from django.core.files import uploadhandler
|
from django.core.files import uploadhandler
|
||||||
from django.http.multipartparser import (
|
from django.http import parsers
|
||||||
MultiPartParser,
|
from django.http.multipartparser import MultiPartParser
|
||||||
MultiPartParserError,
|
|
||||||
TooManyFilesSent,
|
|
||||||
)
|
|
||||||
from django.utils.datastructures import (
|
from django.utils.datastructures import (
|
||||||
CaseInsensitiveMapping,
|
CaseInsensitiveMapping,
|
||||||
ImmutableList,
|
ImmutableList,
|
||||||
@ -362,32 +358,26 @@ class HttpRequest:
|
|||||||
self._mark_post_parse_error()
|
self._mark_post_parse_error()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.content_type == "multipart/form-data":
|
# TODO create a parsers setter/getter/initializer like upload_handlers
|
||||||
if hasattr(self, "_body"):
|
parser_list = (parsers.FormParser(), parsers.MultiPartParser())
|
||||||
# Use already read data
|
|
||||||
data = BytesIO(self._body)
|
selected_parser = None
|
||||||
else:
|
for parser in parser_list:
|
||||||
data = self
|
if self.content_type == parser.media_type:
|
||||||
|
selected_parser = parser
|
||||||
|
break
|
||||||
|
|
||||||
|
if selected_parser:
|
||||||
try:
|
try:
|
||||||
self._post, self._files = self.parse_file_upload(self.META, data)
|
self._post, self._files = parser.parse(self)
|
||||||
except (MultiPartParserError, TooManyFilesSent):
|
except Exception as e:
|
||||||
|
# TODO 'application/x-www-form-urlencoded' didn't do this.
|
||||||
# An error occurred while parsing POST data. Since when
|
# An error occurred while parsing POST data. Since when
|
||||||
# formatting the error the request handler might access
|
# formatting the error the request handler might access
|
||||||
# self.POST, set self._post and self._file to prevent
|
# self.POST, set self._post and self._file to prevent
|
||||||
# attempts to parse POST data again.
|
# attempts to parse POST data again.
|
||||||
self._mark_post_parse_error()
|
self._mark_post_parse_error()
|
||||||
raise
|
raise e
|
||||||
elif self.content_type == "application/x-www-form-urlencoded":
|
|
||||||
# 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:
|
else:
|
||||||
self._post, self._files = (
|
self._post, self._files = (
|
||||||
QueryDict(encoding=self._encoding),
|
QueryDict(encoding=self._encoding),
|
||||||
|
@ -387,20 +387,20 @@ class RequestsTests(SimpleTestCase):
|
|||||||
|
|
||||||
def test_non_utf8_charset_POST_bad_request(self):
|
def test_non_utf8_charset_POST_bad_request(self):
|
||||||
payload = FakePayload(urlencode({"key": "España".encode("latin-1")}))
|
payload = FakePayload(urlencode({"key": "España".encode("latin-1")}))
|
||||||
request = WSGIRequest(
|
environ = {
|
||||||
{
|
"REQUEST_METHOD": "POST",
|
||||||
"REQUEST_METHOD": "POST",
|
"CONTENT_LENGTH": len(payload),
|
||||||
"CONTENT_LENGTH": len(payload),
|
"CONTENT_TYPE": "application/x-www-form-urlencoded; charset=iso-8859-1",
|
||||||
"CONTENT_TYPE": "application/x-www-form-urlencoded; charset=iso-8859-1",
|
"wsgi.input": payload,
|
||||||
"wsgi.input": payload,
|
}
|
||||||
}
|
request = WSGIRequest(environ)
|
||||||
)
|
|
||||||
msg = (
|
msg = (
|
||||||
"HTTP requests with the 'application/x-www-form-urlencoded' content type "
|
"HTTP requests with the 'application/x-www-form-urlencoded' content type "
|
||||||
"must be UTF-8 encoded."
|
"must be UTF-8 encoded."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(BadRequest, msg):
|
with self.assertRaisesMessage(BadRequest, msg):
|
||||||
request.POST
|
request.POST
|
||||||
|
request = WSGIRequest(environ)
|
||||||
with self.assertRaisesMessage(BadRequest, msg):
|
with self.assertRaisesMessage(BadRequest, msg):
|
||||||
request.FILES
|
request.FILES
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user