Skip to content
This repository has been archived by the owner on Jan 13, 2021. It is now read-only.

Commit

Permalink
Merge pull request #204 from Lukasa/map_replace_in_place
Browse files Browse the repository at this point in the history
Fixup HTTPHeaderMap replacing.
  • Loading branch information
Lukasa committed Feb 20, 2016
2 parents 1190b03 + 1015cf3 commit b428195
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 13 deletions.
8 changes: 8 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Release History
===============

dev
---

*Bugfixes*

- Overriding HTTP/2 special headers no longer leads to ill-formed header blocks
with special headers at the end.

0.5.0 (2015-10-11)
------------------

Expand Down
27 changes: 20 additions & 7 deletions hyper/common/headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,28 @@ def iter_raw(self):
def replace(self, key, value):
"""
Replace existing header with new value. If header doesn't exist this
method work like ``__setitem__``. Replacing leads to deletion of all
exsiting headers with the same name.
method work like ``__setitem__``. Replacing leads to deletion of all
existing headers with the same name.
"""
try:
del self[key]
except KeyError:
pass
key = to_bytestring(key)
indices = []
for (i, (k, v)) in enumerate(self._items):
if _keys_equal(k, key):
indices.append(i)

# If the key isn't present, this is easy: just append and abort early.
if not indices:
self._items.append((key, value))
return

# Delete all but the first. I swear, this is the correct slicing
# syntax!
base_index = indices[0]
for i in indices[:0:-1]:
self._items.pop(i)

self[key] = value
del self._items[base_index]
self._items.insert(base_index, (key, value))

def merge(self, other):
"""
Expand Down
2 changes: 1 addition & 1 deletion test/test_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ def test_replacing(self):

assert list(h.items()) == [
(b'name', b'value'),
(b'name3', b'value3'),
(b'name2', b'42'),
(b'name3', b'value3'),
(b'name4', b'other_value'),
]

10 changes: 5 additions & 5 deletions test/test_hyper.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ def test_putheader_replaces_headers(self):
assert list(s.headers.items()) == [
(b':method', b'GET'),
(b':scheme', b'https'),
(b':path', b'/'),
(b':authority', b'www.example.org'),
(b':path', b'/'),
(b'name', b'value2'),
]

Expand Down Expand Up @@ -581,7 +581,7 @@ def test_recv_cb_n_times(self):

def consume_single_frame():
mutable['counter'] += 1

c._consume_single_frame = consume_single_frame
c._recv_cb()

Expand Down Expand Up @@ -779,7 +779,7 @@ def test_streams_can_replace_none_headers(self):
(b"name", b"value"),
(b"other_name", b"other_value")
]

def test_stream_opening_sends_headers(self):
def data_callback(frame):
assert isinstance(frame, HeadersFrame)
Expand Down Expand Up @@ -1548,7 +1548,7 @@ def test_connection_error_when_send_out_of_range_frame(self):
class NullEncoder(object):
@staticmethod
def encode(headers):

def to_str(v):
if is_py2:
return str(v)
Expand All @@ -1557,7 +1557,7 @@ def to_str(v):
v = str(v, 'utf-8')
return v

return '\n'.join("%s%s" % (to_str(name), to_str(val))
return '\n'.join("%s%s" % (to_str(name), to_str(val))
for name, val in headers)


Expand Down

0 comments on commit b428195

Please sign in to comment.