Commit 6f131873 authored by Curtis Maloney's avatar Curtis Maloney Committed by Tim Graham
Browse files

Fixed #26014 -- Added WSGIRequest content_type and content_params attributes.

Parsed the CONTENT_TYPE header once and recorded it on the request.
parent dca8b916
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -98,14 +98,14 @@ class WSGIRequest(http.HttpRequest):
        self.META['PATH_INFO'] = path_info
        self.META['SCRIPT_NAME'] = script_name
        self.method = environ['REQUEST_METHOD'].upper()
        _, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
        if 'charset' in content_params:
        self.content_type, self.content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
        if 'charset' in self.content_params:
            try:
                codecs.lookup(content_params['charset'])
                codecs.lookup(self.content_params['charset'])
            except LookupError:
                pass
            else:
                self.encoding = content_params['charset']
                self.encoding = self.content_params['charset']
        self._post_parse_error = False
        try:
            content_length = int(environ.get('CONTENT_LENGTH'))
+4 −2
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ class HttpRequest(object):
        self.method = None
        self.resolver_match = None
        self._post_parse_error = False
        self.content_type = None
        self.content_params = None

    def __repr__(self):
        if self.method is None or not self.get_full_path():
@@ -278,7 +280,7 @@ class HttpRequest(object):
            self._mark_post_parse_error()
            return

        if self.META.get('CONTENT_TYPE', '').startswith('multipart/form-data'):
        if self.content_type == 'multipart/form-data':
            if hasattr(self, '_body'):
                # Use already read data
                data = BytesIO(self._body)
@@ -296,7 +298,7 @@ class HttpRequest(object):
                # empty POST
                self._mark_post_parse_error()
                raise
        elif self.META.get('CONTENT_TYPE', '').startswith('application/x-www-form-urlencoded'):
        elif self.content_type == 'application/x-www-form-urlencoded':
            self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
        else:
            self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
+14 −0
Original line number Diff line number Diff line
@@ -84,6 +84,20 @@ All attributes should be considered read-only, unless stated otherwise.
    from ``GET`` or ``POST``) will use the new ``encoding`` value.  Useful if
    you know the form data is not in the :setting:`DEFAULT_CHARSET` encoding.

.. attribute:: HttpRequest.content_type

    .. versionadded:: 1.10

    A string representing the MIME type of the request, parsed from the
    ``CONTENT_TYPE`` header.

.. attribute:: HttpRequest.content_params

    .. versionadded:: 1.10

    A dictionary of key/value parameters included in the ``CONTENT_TYPE``
    header.

.. attribute:: HttpRequest.GET

    A dictionary-like object containing all given HTTP GET parameters. See the
+5 −0
Original line number Diff line number Diff line
@@ -299,6 +299,11 @@ Requests and Responses
  :meth:`~django.http.HttpResponse.seekable()` to make an instance a
  stream-like object and allow wrapping it with :py:class:`io.TextIOWrapper`.

* Added the :attr:`HttpResponse.content_type
  <django.http.HttpRequest.content_type>` and
  :attr:`~django.http.HttpRequest.content_params` attributes which are
  parsed from the ``CONTENT_TYPE`` header.

Serialization
~~~~~~~~~~~~~

+15 −2
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ class RequestsTests(SimpleTestCase):
        # and FILES should be MultiValueDict
        self.assertEqual(request.FILES.getlist('foo'), [])

        self.assertIsNone(request.content_type)
        self.assertIsNone(request.content_params)

    def test_httprequest_full_path(self):
        request = HttpRequest()
        request.path = request.path_info = '/;some/?awful/=path/foo:bar/'
@@ -72,14 +75,24 @@ class RequestsTests(SimpleTestCase):
        self.assertEqual(repr(request), str_prefix("<HttpRequest>"))

    def test_wsgirequest(self):
        request = WSGIRequest({'PATH_INFO': 'bogus', 'REQUEST_METHOD': 'bogus', 'wsgi.input': BytesIO(b'')})
        request = WSGIRequest({
            'PATH_INFO': 'bogus',
            'REQUEST_METHOD': 'bogus',
            'CONTENT_TYPE': 'text/html; charset=utf8',
            'wsgi.input': BytesIO(b''),
        })
        self.assertEqual(list(request.GET.keys()), [])
        self.assertEqual(list(request.POST.keys()), [])
        self.assertEqual(list(request.COOKIES.keys()), [])
        self.assertEqual(set(request.META.keys()), {'PATH_INFO', 'REQUEST_METHOD', 'SCRIPT_NAME', 'wsgi.input'})
        self.assertEqual(
            set(request.META.keys()),
            {'PATH_INFO', 'REQUEST_METHOD', 'SCRIPT_NAME', 'CONTENT_TYPE', 'wsgi.input'}
        )
        self.assertEqual(request.META['PATH_INFO'], 'bogus')
        self.assertEqual(request.META['REQUEST_METHOD'], 'bogus')
        self.assertEqual(request.META['SCRIPT_NAME'], '')
        self.assertEqual(request.content_type, 'text/html')
        self.assertEqual(request.content_params, {'charset': 'utf8'})

    def test_wsgirequest_with_script_name(self):
        """