Ticket #5611: 5611-6.diff

File 5611-6.diff, 8.4 KB (added by Claude Paroz, 12 years ago)

CONTENT_TYPE defaulting to the empty string

  • django/core/servers/basehttp.py

    diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
    index 19b287a..2c2bf71 100644
    a b class WSGIRequestHandler(simple_server.WSGIRequestHandler, object):  
    151151        env['PATH_INFO'] = unquote(path)
    152152        env['QUERY_STRING'] = query
    153153        env['REMOTE_ADDR'] = self.client_address[0]
    154         env['CONTENT_TYPE'] = self.headers.get('content-type', 'text/plain')
     154        env['CONTENT_TYPE'] = self.headers.get('content-type', '')
    155155
    156156        length = self.headers.get('content-length')
    157157        if length:
  • django/http/__init__.py

    diff --git a/django/http/__init__.py b/django/http/__init__.py
    index b385b45..95e5002 100644
    a b class HttpRequest(object):  
    315315        self._post_parse_error = True
    316316
    317317    def _load_post_and_files(self):
    318         # Populates self._post and self._files
     318        """ Populates self._post and self._files if the content-type is a form type """
    319319        if self.method != 'POST':
    320320            self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
    321321            return
    class HttpRequest(object):  
    323323            self._mark_post_parse_error()
    324324            return
    325325
    326         if self.META.get('CONTENT_TYPE', '').startswith('multipart'):
     326        if self.META.get('CONTENT_TYPE', '').startswith('multipart/form-data'):
    327327            if hasattr(self, '_body'):
    328328                # Use already read data
    329329                data = BytesIO(self._body)
    class HttpRequest(object):  
    341341                # empty POST
    342342                self._mark_post_parse_error()
    343343                raise
    344         else:
     344        elif self.META.get('CONTENT_TYPE', '').startswith('application/x-www-form-urlencoded'):
    345345            self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
     346        else:
     347            self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
    346348
    347349    ## File-like and iterator interface.
    348350    ##
  • docs/ref/request-response.txt

    diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
    index 0a337eb..860bfe1 100644
    a b All attributes should be considered read-only, unless stated otherwise below.  
    9292
    9393.. attribute:: HttpRequest.POST
    9494
    95     A dictionary-like object containing all given HTTP POST parameters. See the
     95    A dictionary-like object containing all given HTTP POST parameters,
     96    providing that the request contains form data. See the
    9697    :class:`QueryDict` documentation below.
    9798
     99    .. versionchanged:: 1.5
     100        Before Django 1.5, HttpRequest.POST did also contain non-form data. Now if
     101        the ``Content-Type`` header is not ``multipart/form-data`` or
     102        ``application/x-www-form-urlencoded``, you should access the posted data
     103        through :attr:`HttpRequest.body` instead.
     104
    98105    It's possible that a request can come in via POST with an empty ``POST``
    99106    dictionary -- if, say, a form is requested via the POST HTTP method but
    100107    does not include form data. Therefore, you shouldn't use ``if request.POST``
  • docs/releases/1.5.txt

    diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt
    index d49bae8..b60761d 100644
    a b For consistency with the design of the other generic views,  
    245245dictionary into the context, instead passing the variables from the URLconf
    246246directly into the context.
    247247
     248Non-form data in HTTP requests
     249~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     250
     251:attr:`request.POST <django.http.HttpRequest.POST>` will no longer include data
     252posted via HTTP requests with non form-specific content-types in the header.
     253In prior versions, data posted with content-types other than
     254``multipart/form-data`` or ``application/x-www-form-urlencoded`` would still
     255end up represented in the :attr:`request.POST <django.http.HttpRequest.POST>`
     256attribute. Developers wishing to access the raw POST data for these cases,
     257should use the :attr:`request.body <django.http.HttpRequest.body>` attribute
     258instead.
     259
     260For requests without a ``Content-Type`` header, this conforms to the HTTP
     261specification (:rfc:`2616`) which states that: *If the media type remains
     262unknown, the recipient SHOULD treat it as type "application/octet-stream"*.
     263
    248264OPTIONS, PUT and DELETE requests in the test client
    249265~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    250266
  • tests/regressiontests/requests/tests.py

    diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py
    index d801613..378b4cf 100644
    a b class RequestsTests(unittest.TestCase):  
    330330    def test_stream(self):
    331331        payload = b'name=value'
    332332        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     333                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    333334                               'CONTENT_LENGTH': len(payload),
    334335                               'wsgi.input': BytesIO(payload)})
    335336        self.assertEqual(request.read(), b'name=value')
    class RequestsTests(unittest.TestCase):  
    341342        """
    342343        payload = b'name=value'
    343344        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     345                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    344346                               'CONTENT_LENGTH': len(payload),
    345347                               'wsgi.input': BytesIO(payload)})
    346348        self.assertEqual(request.POST, {'name': ['value']})
    class RequestsTests(unittest.TestCase):  
    354356        """
    355357        payload = b'name=value'
    356358        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     359                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    357360                               'CONTENT_LENGTH': len(payload),
    358361                               'wsgi.input': BytesIO(payload)})
    359362        self.assertEqual(request.read(2), b'na')
    class RequestsTests(unittest.TestCase):  
    402405                               'wsgi.input': BytesIO(payload)})
    403406        self.assertEqual(request.POST, {})
    404407
     408    def test_POST_binary_only(self):
     409        payload = b'\r\n\x01\x00\x00\x00ab\x00\x00\xcd\xcc,@'
     410        environ = {'REQUEST_METHOD': 'POST',
     411                   'CONTENT_TYPE': 'application/octet-stream',
     412                   'CONTENT_LENGTH': len(payload),
     413                   'wsgi.input': BytesIO(payload)}
     414        request = WSGIRequest(environ)
     415        self.assertEqual(request.POST, {})
     416        self.assertEqual(request.FILES, {})
     417        self.assertEqual(request.body, payload)
     418
     419        # Same test without specifying content-type
     420        environ.update({'CONTENT_TYPE': '', 'wsgi.input': BytesIO(payload)})
     421        request = WSGIRequest(environ)
     422        self.assertEqual(request.POST, {})
     423        self.assertEqual(request.FILES, {})
     424        self.assertEqual(request.body, payload)
     425
    405426    def test_read_by_lines(self):
    406427        payload = b'name=value'
    407428        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     429                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    408430                               'CONTENT_LENGTH': len(payload),
    409431                               'wsgi.input': BytesIO(payload)})
    410432        self.assertEqual(list(request), [b'name=value'])
    class RequestsTests(unittest.TestCase):  
    415437        """
    416438        payload = b'name=value'
    417439        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     440                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    418441                               'CONTENT_LENGTH': len(payload),
    419442                               'wsgi.input': BytesIO(payload)})
    420443        raw_data = request.body
    class RequestsTests(unittest.TestCase):  
    427450        """
    428451        payload = b'name=value'
    429452        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     453                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    430454                               'CONTENT_LENGTH': len(payload),
    431455                               'wsgi.input': BytesIO(payload)})
    432456        raw_data = request.body
    class RequestsTests(unittest.TestCase):  
    479503
    480504        payload = b'name=value'
    481505        request = WSGIRequest({'REQUEST_METHOD': 'POST',
     506                               'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    482507                               'CONTENT_LENGTH': len(payload),
    483508                               'wsgi.input': ExplodingBytesIO(payload)})
    484509
Back to Top