Skip to content
Browse files

Unicodify the header name (key) as well as value

In Python 2 using a Headers object as so,

    h = Headers()
    h[b'X-Foo'] = b'something'


    X-Foo: something

in the actual HTTP message, whereas in Python 3 it is

    b'X-Foo': something

this is because only the value is currently unicodified. This change
ensures the header name (key) is also unicodified as well therefore
matching the Python 2 usage and the expected usage.

This also removes a regression test for unicode header keys that is
not required. It was recognised in flask#758 as resulting in a HTTP
message containing,

    u'X-Foo': something

however this behaviour was fixed in
f3435a3 introducing the test, broken
in 6049a4f and then comprehensively
fixed in db00dfb. Therefore with the
last commit and tests as added the regression test is not required.
  • Loading branch information...
pgjones authored and davidism committed Aug 25, 2018
1 parent 38ec0b2 commit 42c6d29da25069162f1bf8b57af613109fd5ac1e
Showing with 19 additions and 12 deletions.
  1. +13 −0 tests/
  2. +0 −11 tests/
  3. +6 −1 werkzeug/
@@ -746,9 +746,11 @@ def test_bytes_operations(self):
h = self.storage_class()
h.set('X-Foo-Poo', 'bleh')
h.set('X-Whoops', b'\xff')
h.set(b'X-Bytes', b'something')

assert h.get('x-foo-poo', as_bytes=True) == b'bleh'
assert h.get('x-whoops', as_bytes=True) == b'\xff'
assert h.get('x-bytes') == 'something'

def test_to_wsgi_list(self):
h = self.storage_class()
@@ -761,6 +763,17 @@ def test_to_wsgi_list(self):
strict_eq(key, u'Key')
strict_eq(value, u'Value')

def test_to_wsgi_list_bytes(self):
h = self.storage_class()
h.set(b'Key', b'Value')
for key, value in h.to_wsgi_list():
if PY2:
strict_eq(key, b'Key')
strict_eq(value, b'Value')
strict_eq(key, u'Key')
strict_eq(value, u'Value')

class TestEnvironHeaders(object):
storage_class = datastructures.EnvironHeaders
@@ -39,17 +39,6 @@ def test_redirect():
assert resp.status_code == 305

def test_redirect_no_unicode_header_keys():
# Make sure all headers are native keys. This was a bug at one point
# due to an incorrect conversion.
resp = utils.redirect('', 305)
for key, value in resp.headers.items():
assert type(key) == str
assert type(value) == text_type
assert resp.headers['Location'] == ''
assert resp.status_code == 305

def test_redirect_xss():
location = '"><script>alert(1)</script>'
resp = utils.redirect(location)
@@ -1161,6 +1161,7 @@ def add(self, _key, _value, **kw):
if kw:
_value = _options_header_vkw(_value, kw)
_key = _unicodify_header_value(_key)
_value = _unicodify_header_value(_value)
self._list.append((_key, _value))
@@ -1201,6 +1202,7 @@ def set(self, _key, _value, **kw):
if kw:
_value = _options_header_vkw(_value, kw)
_key = _unicodify_header_value(_key)
_value = _unicodify_header_value(_value)
if not self._list:
@@ -1236,7 +1238,10 @@ def __setitem__(self, key, value):
if isinstance(key, (slice, integer_types)):
if isinstance(key, integer_types):
value = [value]
value = [(k, _unicodify_header_value(v)) for (k, v) in value]
value = [
(_unicodify_header_value(k), _unicodify_header_value(v))
for (k, v) in value
[self._validate_value(v) for (k, v) in value]
if isinstance(key, integer_types):
self._list[key] = value[0]

0 comments on commit 42c6d29

Please sign in to comment.
You can’t perform that action at this time.