Ticket #5076: 5076-3.diff

File 5076-3.diff, 2.9 KB (added by claudep, 3 years ago)

Get request encoding from content-type header

  • django/core/handlers/wsgi.py

    diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
    index 45cb226..2b99b38 100644
    a b  
    11from __future__ import unicode_literals
    22
     3import codecs
    34import logging
    45import sys
    56from io import BytesIO
    class WSGIRequest(http.HttpRequest): 
    144145        self.META['PATH_INFO'] = path_info
    145146        self.META['SCRIPT_NAME'] = script_name
    146147        self.method = environ['REQUEST_METHOD'].upper()
     148        _, content_params = self._parse_content_type(self.META.get('CONTENT_TYPE', ''))
     149        if 'charset' in content_params:
     150            try:
     151                codecs.lookup(content_params['charset'])
     152            except LookupError:
     153                pass
     154            else:
     155                self.encoding = content_params['charset']
    147156        self._post_parse_error = False
    148157        try:
    149158            content_length = int(self.environ.get('CONTENT_LENGTH'))
    class WSGIRequest(http.HttpRequest): 
    155164    def _is_secure(self):
    156165        return 'wsgi.url_scheme' in self.environ and self.environ['wsgi.url_scheme'] == 'https'
    157166
     167    def _parse_content_type(self, ctype):
     168        """
     169        Example input: "text/plain; charset=iso-8859-1"
     170        Return: ('text/plain', {'charset': 'iso-8859-1'})
     171        """
     172        content_type, _, params = ctype.partition(';')
     173        content_params = {}
     174        for parameter in params.split(';'):
     175            k, _, v = parameter.strip().partition('=')
     176            content_params[k] = v
     177        return content_type, content_params
     178
    158179    def _get_request(self):
    159180        if not hasattr(self, '_request'):
    160181            self._request = datastructures.MergeDict(self.POST, self.GET)
  • tests/regressiontests/requests/tests.py

    diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py
    index 6522620..eaf25ea 100644
    a b  
     1# -*- encoding: utf-8 -*-
    12from __future__ import unicode_literals
    23
    34import time
    class RequestsTests(unittest.TestCase): 
    352353        self.assertRaises(Exception, lambda: request.body)
    353354        self.assertEqual(request.POST, {})
    354355
     356    def test_alternate_charset_POST(self):
     357        """
     358        Test a POST with non-utf-8 payload encoding.
     359        """
     360        from django.utils.http import urllib_parse
     361        payload = FakePayload(urllib_parse.urlencode({'key': 'España'.encode('latin-1')}))
     362        request = WSGIRequest({
     363            'REQUEST_METHOD': 'POST',
     364            'CONTENT_LENGTH': len(payload),
     365            'CONTENT_TYPE': 'application/x-www-form-urlencoded; charset=iso-8859-1',
     366            'wsgi.input': payload,
     367        })
     368        self.assertEqual(request.POST, {'key': ['España']})
     369
    355370    def test_body_after_POST_multipart(self):
    356371        """
    357372        Reading body after parsing multipart is not allowed
Back to Top