Skip to content

Commit b7b20fa

Browse files
author
connabyss
committed
Assert the duplicate Host error message in the test
Move the duplicate Host header cases into their own list and add a test that checks the ProtocolError says "Request header block has multiple Host headers", so it fails if any other header check rejects these blocks instead. The cases stay in the general invalid header list too. Assisted-by: Claude Code
1 parent 2b486a7 commit b7b20fa

1 file changed

Lines changed: 30 additions & 4 deletions

File tree

‎tests/test_invalid_headers.py‎

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ class TestInvalidFrameSequences:
3333
(":method", "GET"),
3434
("user-agent", "someua/0.0.1"),
3535
]
36+
duplicate_host_header_blocks = [
37+
[*base_request_headers, ("host", "example.com"), ("host", "evil.example.com")],
38+
[*base_request_headers, ("host", "evil.example.com"), ("host", "example.com")],
39+
[*[header for header in base_request_headers if header[0] != ":authority"],
40+
("host", "example.com"), ("host", "evil.example.com")],
41+
]
3642
base_invalid_header_blocks = [
3743
[*base_request_headers, ("Uppercase", "name")],
3844
[*base_request_headers, (":late", "pseudo-header")],
@@ -43,10 +49,7 @@ class TestInvalidFrameSequences:
4349
[*base_request_headers, ("transfer-encoding", "gzip")],
4450
[*base_request_headers, ("upgrade", "super-protocol/1.1")],
4551
[*base_request_headers, ("te", "chunked")],
46-
[*base_request_headers, ("host", "example.com"), ("host", "evil.example.com")],
47-
[*base_request_headers, ("host", "evil.example.com"), ("host", "example.com")],
48-
[*[header for header in base_request_headers if header[0] != ":authority"],
49-
("host", "example.com"), ("host", "evil.example.com")],
52+
*duplicate_host_header_blocks,
5053
[*base_request_headers, ("host", "notexample.com")],
5154
[*base_request_headers, (" name", "name with leading space")],
5255
[*base_request_headers, ("name ", "name with trailing space")],
@@ -91,6 +94,29 @@ def test_headers_event(self, frame_factory, headers) -> None:
9194
)
9295
assert c.data_to_send() == expected_frame.serialize()
9396

97+
@pytest.mark.parametrize("headers", duplicate_host_header_blocks + [
98+
h2.utilities.utf8_encode_headers(headers) for headers in duplicate_host_header_blocks
99+
])
100+
def test_duplicate_host_headers_rejected(self, frame_factory, headers) -> None:
101+
"""
102+
A request header block with more than one Host header is rejected
103+
by the duplicate Host check, not by any other header check.
104+
"""
105+
c = h2.connection.H2Connection(config=self.server_config)
106+
c.receive_data(frame_factory.preamble())
107+
c.clear_outbound_data_buffer()
108+
109+
f = frame_factory.build_headers_frame(headers)
110+
data = f.serialize()
111+
112+
with pytest.raises(h2.exceptions.ProtocolError, match="Request header block has multiple Host headers"):
113+
c.receive_data(data)
114+
115+
expected_frame = frame_factory.build_goaway_frame(
116+
last_stream_id=1, error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR,
117+
)
118+
assert c.data_to_send() == expected_frame.serialize()
119+
94120
@pytest.mark.parametrize("headers", invalid_header_blocks)
95121
def test_push_promise_event(self, frame_factory, headers) -> None:
96122
"""

0 commit comments

Comments
 (0)