Skip to content

Commit 7d50c07

Browse files
committed
Support multiple Sec-WebSocket-Extensions and Sec-WebSocket-Protocol headers
These headers may be present multiple times and hence should be appended together as per RFC6455.
1 parent f51aa84 commit 7d50c07

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

src/wsproto/handshake.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,12 @@ def _process_connection_request( # noqa: MC0001
201201
host = value.decode("idna")
202202
continue # Skip appending to headers
203203
elif name == b"sec-websocket-extensions":
204-
extensions = split_comma_header(value)
204+
extensions.extend(split_comma_header(value))
205205
continue # Skip appending to headers
206206
elif name == b"sec-websocket-key":
207207
key = value
208208
elif name == b"sec-websocket-protocol":
209-
subprotocols = split_comma_header(value)
209+
subprotocols.extend(split_comma_header(value))
210210
continue # Skip appending to headers
211211
elif name == b"sec-websocket-version":
212212
version = value

test/test_handshake.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,45 @@ def test_send_invalid_event() -> None:
5858
client = H11Handshake(CLIENT)
5959
with pytest.raises(LocalProtocolError):
6060
client.send(Ping())
61+
62+
63+
def test_h11_multiple_headers_handshake() -> None:
64+
server = H11Handshake(SERVER)
65+
data = (
66+
b"GET wss://api.website.xyz/ws HTTP/1.1\r\n"
67+
b"Host: api.website.xyz\r\n"
68+
b"Connection: Upgrade\r\n"
69+
b"Pragma: no-cache\r\n"
70+
b"Cache-Control: no-cache\r\n"
71+
b"User-Agent: Mozilla/5.0 (X11; Linux x86_64) "
72+
b"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36\r\n"
73+
b"Upgrade: websocket\r\n"
74+
b"Origin: https://website.xyz\r\n"
75+
b"Sec-WebSocket-Version: 13\r\n"
76+
b"Accept-Encoding: gzip, deflate, br\r\n"
77+
b"Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\r\n"
78+
b"Sec-WebSocket-Key: tOzeAzi9xK7ADxxEdTzmaA==\r\n"
79+
b"Sec-WebSocket-Extensions: this-extension; isnt-seen, even-tho, it-should-be\r\n"
80+
b"Sec-WebSocket-Protocol: there-protocols\r\n"
81+
b"Sec-WebSocket-Protocol: arent-seen\r\n"
82+
b"Sec-WebSocket-Extensions: this-extension; were-gonna-see, and-another-extension; were-also; gonna-see=100; percent\r\n" # noqa: E501
83+
b"Sec-WebSocket-Protocol: only-these-protocols, are-seen, from-the-request-object\r\n"
84+
b"\r\n"
85+
)
86+
server.receive_data(data)
87+
request = next(server.events())
88+
assert isinstance(request, Request)
89+
assert request.subprotocols == [
90+
"there-protocols",
91+
"arent-seen",
92+
"only-these-protocols",
93+
"are-seen",
94+
"from-the-request-object",
95+
]
96+
assert request.extensions == [
97+
"this-extension; isnt-seen",
98+
"even-tho",
99+
"it-should-be",
100+
"this-extension; were-gonna-see",
101+
"and-another-extension; were-also; gonna-see=100; percent",
102+
]

0 commit comments

Comments
 (0)