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

Commit b428195

Browse files
committed
Merge pull request #204 from Lukasa/map_replace_in_place
Fixup HTTPHeaderMap replacing.
2 parents 1190b03 + 1015cf3 commit b428195

File tree

4 files changed

+34
-13
lines changed

4 files changed

+34
-13
lines changed

HISTORY.rst

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
Release History
22
===============
33

4+
dev
5+
---
6+
7+
*Bugfixes*
8+
9+
- Overriding HTTP/2 special headers no longer leads to ill-formed header blocks
10+
with special headers at the end.
11+
412
0.5.0 (2015-10-11)
513
------------------
614

hyper/common/headers.py

+20-7
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,28 @@ def iter_raw(self):
184184
def replace(self, key, value):
185185
"""
186186
Replace existing header with new value. If header doesn't exist this
187-
method work like ``__setitem__``. Replacing leads to deletion of all
188-
exsiting headers with the same name.
187+
method work like ``__setitem__``. Replacing leads to deletion of all
188+
existing headers with the same name.
189189
"""
190-
try:
191-
del self[key]
192-
except KeyError:
193-
pass
190+
key = to_bytestring(key)
191+
indices = []
192+
for (i, (k, v)) in enumerate(self._items):
193+
if _keys_equal(k, key):
194+
indices.append(i)
195+
196+
# If the key isn't present, this is easy: just append and abort early.
197+
if not indices:
198+
self._items.append((key, value))
199+
return
200+
201+
# Delete all but the first. I swear, this is the correct slicing
202+
# syntax!
203+
base_index = indices[0]
204+
for i in indices[:0:-1]:
205+
self._items.pop(i)
194206

195-
self[key] = value
207+
del self._items[base_index]
208+
self._items.insert(base_index, (key, value))
196209

197210
def merge(self, other):
198211
"""

test/test_headers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ def test_replacing(self):
272272

273273
assert list(h.items()) == [
274274
(b'name', b'value'),
275-
(b'name3', b'value3'),
276275
(b'name2', b'42'),
276+
(b'name3', b'value3'),
277277
(b'name4', b'other_value'),
278278
]
279279

test/test_hyper.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ def test_putheader_replaces_headers(self):
122122
assert list(s.headers.items()) == [
123123
(b':method', b'GET'),
124124
(b':scheme', b'https'),
125-
(b':path', b'/'),
126125
(b':authority', b'www.example.org'),
126+
(b':path', b'/'),
127127
(b'name', b'value2'),
128128
]
129129

@@ -581,7 +581,7 @@ def test_recv_cb_n_times(self):
581581

582582
def consume_single_frame():
583583
mutable['counter'] += 1
584-
584+
585585
c._consume_single_frame = consume_single_frame
586586
c._recv_cb()
587587

@@ -779,7 +779,7 @@ def test_streams_can_replace_none_headers(self):
779779
(b"name", b"value"),
780780
(b"other_name", b"other_value")
781781
]
782-
782+
783783
def test_stream_opening_sends_headers(self):
784784
def data_callback(frame):
785785
assert isinstance(frame, HeadersFrame)
@@ -1548,7 +1548,7 @@ def test_connection_error_when_send_out_of_range_frame(self):
15481548
class NullEncoder(object):
15491549
@staticmethod
15501550
def encode(headers):
1551-
1551+
15521552
def to_str(v):
15531553
if is_py2:
15541554
return str(v)
@@ -1557,7 +1557,7 @@ def to_str(v):
15571557
v = str(v, 'utf-8')
15581558
return v
15591559

1560-
return '\n'.join("%s%s" % (to_str(name), to_str(val))
1560+
return '\n'.join("%s%s" % (to_str(name), to_str(val))
15611561
for name, val in headers)
15621562

15631563

0 commit comments

Comments
 (0)