Fixed #21282 -- Made HttpResponse.serialize_headers accept latin-1
Thanks Raphaël Barrois for the report and the initial patch and Aymeric Augustin for the review.
This commit is contained in:
parent
5008706345
commit
a14f087233
|
@ -123,8 +123,11 @@ class HttpResponseBase(six.Iterator):
|
||||||
|
|
||||||
def serialize_headers(self):
|
def serialize_headers(self):
|
||||||
"""HTTP headers as a bytestring."""
|
"""HTTP headers as a bytestring."""
|
||||||
|
def to_bytes(val, encoding):
|
||||||
|
return val if isinstance(val, bytes) else val.encode(encoding)
|
||||||
|
|
||||||
headers = [
|
headers = [
|
||||||
('%s: %s' % (key, value)).encode('us-ascii')
|
(b': '.join([to_bytes(key, 'ascii'), to_bytes(value, 'latin-1')]))
|
||||||
for key, value in self._headers.values()
|
for key, value in self._headers.values()
|
||||||
]
|
]
|
||||||
return b'\r\n'.join(headers)
|
return b'\r\n'.join(headers)
|
||||||
|
@ -135,7 +138,7 @@ class HttpResponseBase(six.Iterator):
|
||||||
__str__ = serialize_headers
|
__str__ = serialize_headers
|
||||||
|
|
||||||
def _convert_to_charset(self, value, charset, mime_encode=False):
|
def _convert_to_charset(self, value, charset, mime_encode=False):
|
||||||
"""Converts headers key/value to ascii/latin1 native strings.
|
"""Converts headers key/value to ascii/latin-1 native strings.
|
||||||
|
|
||||||
`charset` must be 'ascii' or 'latin-1'. If `mime_encode` is True and
|
`charset` must be 'ascii' or 'latin-1'. If `mime_encode` is True and
|
||||||
`value` value can't be represented in the given charset, MIME-encoding
|
`value` value can't be represented in the given charset, MIME-encoding
|
||||||
|
@ -171,7 +174,7 @@ class HttpResponseBase(six.Iterator):
|
||||||
|
|
||||||
def __setitem__(self, header, value):
|
def __setitem__(self, header, value):
|
||||||
header = self._convert_to_charset(header, 'ascii')
|
header = self._convert_to_charset(header, 'ascii')
|
||||||
value = self._convert_to_charset(value, 'latin1', mime_encode=True)
|
value = self._convert_to_charset(value, 'latin-1', mime_encode=True)
|
||||||
self._headers[header.lower()] = (header, value)
|
self._headers[header.lower()] = (header, value)
|
||||||
|
|
||||||
def __delitem__(self, header):
|
def __delitem__(self, header):
|
||||||
|
|
|
@ -254,6 +254,7 @@ class HttpResponseTests(unittest.TestCase):
|
||||||
r['key'] = 'test'.encode('ascii')
|
r['key'] = 'test'.encode('ascii')
|
||||||
self.assertEqual(r['key'], str('test'))
|
self.assertEqual(r['key'], str('test'))
|
||||||
self.assertIsInstance(r['key'], str)
|
self.assertIsInstance(r['key'], str)
|
||||||
|
self.assertIn(b'test', r.serialize_headers())
|
||||||
|
|
||||||
# Latin-1 unicode or bytes values are also converted to native strings.
|
# Latin-1 unicode or bytes values are also converted to native strings.
|
||||||
r['key'] = 'café'
|
r['key'] = 'café'
|
||||||
|
@ -262,11 +263,13 @@ class HttpResponseTests(unittest.TestCase):
|
||||||
r['key'] = 'café'.encode('latin-1')
|
r['key'] = 'café'.encode('latin-1')
|
||||||
self.assertEqual(r['key'], smart_str('café', 'latin-1'))
|
self.assertEqual(r['key'], smart_str('café', 'latin-1'))
|
||||||
self.assertIsInstance(r['key'], str)
|
self.assertIsInstance(r['key'], str)
|
||||||
|
self.assertIn('café'.encode('latin-1'), r.serialize_headers())
|
||||||
|
|
||||||
# Other unicode values are MIME-encoded (there's no way to pass them as bytes).
|
# Other unicode values are MIME-encoded (there's no way to pass them as bytes).
|
||||||
r['key'] = '†'
|
r['key'] = '†'
|
||||||
self.assertEqual(r['key'], str('=?utf-8?b?4oCg?='))
|
self.assertEqual(r['key'], str('=?utf-8?b?4oCg?='))
|
||||||
self.assertIsInstance(r['key'], str)
|
self.assertIsInstance(r['key'], str)
|
||||||
|
self.assertIn(b'=?utf-8?b?4oCg?=', r.serialize_headers())
|
||||||
|
|
||||||
# The response also converts unicode or bytes keys to strings, but requires
|
# The response also converts unicode or bytes keys to strings, but requires
|
||||||
# them to contain ASCII
|
# them to contain ASCII
|
||||||
|
|
Loading…
Reference in New Issue