Ticket #18916: 18916.diff
File 18916.diff, 6.5 KB (added by , 12 years ago) |
---|
-
django/http/__init__.py
diff --git a/django/http/__init__.py b/django/http/__init__.py index 2198f38..b9f29ae 100644
a b from __future__ import absolute_import, unicode_literals 2 2 3 3 import copy 4 4 import datetime 5 from email.header import Header 5 6 import os 6 7 import re 7 8 import sys … … class HttpResponse(object): 560 561 else: 561 562 __str__ = serialize 562 563 563 def _convert_to_ascii(self, *values): 564 """Converts all values to ascii strings.""" 565 for value in values: 566 if not isinstance(value, six.string_types): 567 value = str(value) 568 try: 569 if six.PY3: 570 # Ensure string only contains ASCII 571 value.encode('us-ascii') 564 def _convert_to_charset(self, value, charset, mime_encode=False): 565 """Converts headers key/value to ascii/latin1 native strings 566 567 and optionally MIME-encode if the input doesn't fit in the charset. 568 """ 569 if not isinstance(value, six.string_types): 570 value = str(value) 571 try: 572 if six.PY3: 573 # Ensure string is valid in given charset 574 value.encode(charset) 575 else: 576 if isinstance(value, str): 577 # Ensure string is valid in given charset 578 value.decode(charset) 572 579 else: 573 if isinstance(value, str): 574 # Ensure string only contains ASCII 575 value.decode('us-ascii') 576 else: 577 # Convert unicode to an ASCII string 578 value = value.encode('us-ascii') 579 except UnicodeError as e: 580 e.reason += ', HTTP response headers must be in US-ASCII format' 580 # Convert unicode string to given charset 581 value = value.encode(charset) 582 except UnicodeError as e: 583 if mime_encode: 584 value = Header(value, 'utf-8').encode() 585 else: 586 e.reason += ', HTTP response headers must be in %s format' % charset 581 587 raise 582 if '\n' in value or '\r'in value:583 584 yieldvalue588 if str('\n') in value or str('\r') in value: 589 raise BadHeaderError("Header values can't contain newlines (got %r)" % value) 590 return value 585 591 586 592 def __setitem__(self, header, value): 587 header, value = self._convert_to_ascii(header, value) 593 header = self._convert_to_charset(header, 'ascii') 594 value = self._convert_to_charset(value, 'latin1', mime_encode=True) 588 595 self._headers[header.lower()] = (header, value) 589 596 590 597 def __delitem__(self, header): -
tests/regressiontests/httpwrappers/tests.py
diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py index 21ba198..4c6aed1 100644
a b from django.http import (QueryDict, HttpResponse, HttpResponseRedirect, 11 11 SimpleCookie, BadHeaderError, 12 12 parse_cookie) 13 13 from django.test import TestCase 14 from django.utils.encoding import smart_str 14 15 from django.utils import six 15 16 from django.utils import unittest 16 17 … … class QueryDictTests(unittest.TestCase): 228 229 self.assertEqual(copy.deepcopy(q).encoding, 'iso-8859-15') 229 230 230 231 class HttpResponseTests(unittest.TestCase): 231 def test_unicode_headers(self):232 r = HttpResponse()233 234 # If we insert a unicode value it will be converted to an ascii235 r['value'] = 'test value'236 self.assertTrue(isinstance(r['value'], str))237 238 # An error is raised when a unicode object with non-ascii is assigned.239 self.assertRaises(UnicodeEncodeError, r.__setitem__, 'value', 't\xebst value')240 232 241 # An error is raised when a unicode object with non-ASCII format is 242 # passed as initial mimetype or content_type. 243 self.assertRaises(UnicodeEncodeError, HttpResponse, 244 content_type='t\xebst value') 233 def test_headers_type(self): 234 r = HttpResponse() 245 235 246 # HttpResponse headers must be convertible to ASCII. 247 self.assertRaises(UnicodeEncodeError, HttpResponse, 248 content_type='t\xebst value') 236 # The following tests explicitly test types in addition to values 237 # because in Python 2 u'foo' == b'foo'. 238 239 # ASCII unicode or bytes values are converted to native strings. 240 r['key'] = 'test' 241 self.assertEqual(r['key'], str('test')) 242 self.assertIsInstance(r['key'], str) 243 r['key'] = 'test'.encode('ascii') 244 self.assertEqual(r['key'], str('test')) 245 self.assertIsInstance(r['key'], str) 246 247 # Latin-1 unicode or bytes values are also converted to native strings. 248 r['key'] = 'café' 249 self.assertEqual(r['key'], smart_str('café', 'latin-1')) 250 self.assertIsInstance(r['key'], str) 251 r['key'] = 'café'.encode('latin-1') 252 self.assertEqual(r['key'], smart_str('café', 'latin-1')) 253 self.assertIsInstance(r['key'], str) 254 255 # Other unicode values are MIME-encoded (there's no way to pass them as bytes). 256 r['key'] = '†' 257 self.assertEqual(r['key'], str('=?utf-8?b?4oCg?=')) 258 self.assertIsInstance(r['key'], str) 259 260 # The response also converts unicode or bytes keys to strings, but requires 261 # them to contain ASCII 262 r = HttpResponse() 263 r['foo'] = 'bar' 264 l = list(r.items()) 265 self.assertEqual(l[0], ('foo', 'bar')) 266 self.assertIsInstance(l[0][0], str) 249 267 250 # The response also converts unicode keys to strings.)251 r[ 'test'] = 'testing key'268 r = HttpResponse() 269 r[b'foo'] = 'bar' 252 270 l = list(r.items()) 253 l.sort() 254 self.assertEqual(l[1], ('test', 'testing key')) 271 self.assertEqual(l[0], ('foo', 'bar')) 272 self.assertIsInstance(l[0][0], str) 273 274 r = HttpResponse() 275 self.assertRaises(UnicodeError, r.__setitem__, 'føø', 'bar') 276 self.assertRaises(UnicodeError, r.__setitem__, 'føø'.encode('utf-8'), 'bar') 255 277 256 # It will also raise errors for keys with non-ascii data.257 self.assertRaises(UnicodeEncodeError, r.__setitem__, 't\xebst key', 'value')258 278 259 279 def test_newlines_in_headers(self): 260 280 # Bug #10188: Do not allow newlines in headers (CR or LF)