Loading django/http/response.py +6 −3 Original line number Diff line number Diff line Loading @@ -123,8 +123,11 @@ class HttpResponseBase(six.Iterator): def serialize_headers(self): """HTTP headers as a bytestring.""" def to_bytes(val, encoding): return val if isinstance(val, bytes) else val.encode(encoding) 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() ] return b'\r\n'.join(headers) Loading @@ -135,7 +138,7 @@ class HttpResponseBase(six.Iterator): __str__ = serialize_headers 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 `value` value can't be represented in the given charset, MIME-encoding Loading Loading @@ -171,7 +174,7 @@ class HttpResponseBase(six.Iterator): def __setitem__(self, header, value): 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) def __delitem__(self, header): Loading tests/httpwrappers/tests.py +3 −0 Original line number Diff line number Diff line Loading @@ -254,6 +254,7 @@ class HttpResponseTests(unittest.TestCase): r['key'] = 'test'.encode('ascii') self.assertEqual(r['key'], str('test')) self.assertIsInstance(r['key'], str) self.assertIn(b'test', r.serialize_headers()) # Latin-1 unicode or bytes values are also converted to native strings. r['key'] = 'café' Loading @@ -262,11 +263,13 @@ class HttpResponseTests(unittest.TestCase): r['key'] = 'café'.encode('latin-1') self.assertEqual(r['key'], smart_str('café', 'latin-1')) 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). r['key'] = '†' self.assertEqual(r['key'], str('=?utf-8?b?4oCg?=')) 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 # them to contain ASCII Loading Loading
django/http/response.py +6 −3 Original line number Diff line number Diff line Loading @@ -123,8 +123,11 @@ class HttpResponseBase(six.Iterator): def serialize_headers(self): """HTTP headers as a bytestring.""" def to_bytes(val, encoding): return val if isinstance(val, bytes) else val.encode(encoding) 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() ] return b'\r\n'.join(headers) Loading @@ -135,7 +138,7 @@ class HttpResponseBase(six.Iterator): __str__ = serialize_headers 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 `value` value can't be represented in the given charset, MIME-encoding Loading Loading @@ -171,7 +174,7 @@ class HttpResponseBase(six.Iterator): def __setitem__(self, header, value): 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) def __delitem__(self, header): Loading
tests/httpwrappers/tests.py +3 −0 Original line number Diff line number Diff line Loading @@ -254,6 +254,7 @@ class HttpResponseTests(unittest.TestCase): r['key'] = 'test'.encode('ascii') self.assertEqual(r['key'], str('test')) self.assertIsInstance(r['key'], str) self.assertIn(b'test', r.serialize_headers()) # Latin-1 unicode or bytes values are also converted to native strings. r['key'] = 'café' Loading @@ -262,11 +263,13 @@ class HttpResponseTests(unittest.TestCase): r['key'] = 'café'.encode('latin-1') self.assertEqual(r['key'], smart_str('café', 'latin-1')) 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). r['key'] = '†' self.assertEqual(r['key'], str('=?utf-8?b?4oCg?=')) 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 # them to contain ASCII Loading