1- import asyncio
21import gzip
32import json
43import sys
@@ -332,14 +331,9 @@ def test_server_content_encoding_header(
332331 assert f .read () == b"this is a test"
333332
334333
335- @pytest .fixture (scope = "module" )
336- def event_loop ():
337- loop = asyncio .get_event_loop ()
338- yield loop
339- loop .close ()
340-
341-
342- async def _websocket_echo (a_server_port_and_token : Tuple [int , str ]) -> None :
334+ async def test_server_proxy_websocket_messages (
335+ a_server_port_and_token : Tuple [int , str ]
336+ ) -> None :
343337 PORT = a_server_port_and_token [0 ]
344338 url = f"ws://{ LOCALHOST } :{ PORT } /python-websocket/echosocket"
345339 conn = await websocket_connect (url )
@@ -349,13 +343,7 @@ async def _websocket_echo(a_server_port_and_token: Tuple[int, str]) -> None:
349343 assert msg == expected_msg
350344
351345
352- def test_server_proxy_websocket (
353- event_loop , a_server_port_and_token : Tuple [int , str ]
354- ) -> None :
355- event_loop .run_until_complete (_websocket_echo (a_server_port_and_token ))
356-
357-
358- async def _websocket_headers (a_server_port_and_token : Tuple [int , str ]) -> None :
346+ async def test_server_proxy_websocket_headers (a_server_port_and_token : Tuple [int , str ]):
359347 PORT = a_server_port_and_token [0 ]
360348 url = f"ws://{ LOCALHOST } :{ PORT } /python-websocket/headerssocket"
361349 conn = await websocket_connect (url )
@@ -366,25 +354,68 @@ async def _websocket_headers(a_server_port_and_token: Tuple[int, str]) -> None:
366354 assert headers ["X-Custom-Header" ] == "pytest-23456"
367355
368356
369- def test_server_proxy_websocket_headers (
370- event_loop , a_server_port_and_token : Tuple [int , str ]
357+ @pytest .mark .parametrize (
358+ "client_requested,server_received,server_responded,proxy_responded" ,
359+ [
360+ (None , None , None , None ),
361+ (["first" ], ["first" ], "first" , "first" ),
362+ # IMPORTANT: The tests below verify current bugged behavior, and the
363+ # commented out tests is what we want to succeed!
364+ #
365+ # The proxy websocket should actually respond the handshake
366+ # with a subprotocol based on a the server handshake
367+ # response, but we are finalizing the client/proxy handshake
368+ # before the proxy/server handshake, and that makes it
369+ # impossible. We currently instead just pick the first
370+ # requested protocol no matter what what subprotocol the
371+ # server picks.
372+ #
373+ # Bug 1 - server wasn't passed all subprotocols:
374+ (["first" , "second" ], ["first" ], "first" , "first" ),
375+ # (["first", "second"], ["first", "second"], "first", "first"),
376+ #
377+ # Bug 2 - server_responded doesn't match proxy_responded:
378+ (["first" , "favored" ], ["first" ], "first" , "first" ),
379+ # (["first", "favored"], ["first", "favored"], "favored", "favored"),
380+ (
381+ ["please_select_no_protocol" ],
382+ ["please_select_no_protocol" ],
383+ None ,
384+ "please_select_no_protocol" ,
385+ ),
386+ # (["please_select_no_protocol"], ["please_select_no_protocol"], None, None),
387+ ],
388+ )
389+ async def test_server_proxy_websocket_subprotocols (
390+ a_server_port_and_token : Tuple [int , str ],
391+ client_requested ,
392+ server_received ,
393+ server_responded ,
394+ proxy_responded ,
371395):
372- event_loop .run_until_complete (_websocket_headers (a_server_port_and_token ))
373-
374-
375- async def _websocket_subprotocols (a_server_port_and_token : Tuple [int , str ]) -> None :
376396 PORT , TOKEN = a_server_port_and_token
377397 url = f"ws://{ LOCALHOST } :{ PORT } /python-websocket/subprotocolsocket"
378- conn = await websocket_connect (url , subprotocols = [ "protocol_1" , "protocol_2" ] )
398+ conn = await websocket_connect (url , subprotocols = client_requested )
379399 await conn .write_message ("Hello, world!" )
400+
401+ # verify understanding of websocket_connect that this test relies on
402+ if client_requested :
403+ assert "Sec-Websocket-Protocol" in conn .request .headers
404+ else :
405+ assert "Sec-Websocket-Protocol" not in conn .request .headers
406+
380407 msg = await conn .read_message ()
381- assert json .loads (msg ) == [ "protocol_1" , "protocol_2" ]
408+ info = json .loads (msg )
382409
410+ assert info ["requested_subprotocols" ] == server_received
411+ assert info ["selected_subprotocol" ] == server_responded
412+ assert conn .selected_subprotocol == proxy_responded
383413
384- def test_server_proxy_websocket_subprotocols (
385- event_loop , a_server_port_and_token : Tuple [int , str ]
386- ):
387- event_loop .run_until_complete (_websocket_subprotocols (a_server_port_and_token ))
414+ # verify proxy response headers directly
415+ if proxy_responded is None :
416+ assert "Sec-Websocket-Protocol" not in conn .headers
417+ else :
418+ assert "Sec-Websocket-Protocol" in conn .headers
388419
389420
390421@pytest .mark .parametrize (
@@ -410,7 +441,9 @@ def test_bad_server_proxy_url(
410441 assert "X-ProxyContextPath" not in r .headers
411442
412443
413- def test_callable_environment_formatting (a_server_port_and_token : Tuple [int , str ]) -> None :
444+ def test_callable_environment_formatting (
445+ a_server_port_and_token : Tuple [int , str ]
446+ ) -> None :
414447 PORT , TOKEN = a_server_port_and_token
415448 r = request_get (PORT , "/python-http-callable-env/test" , TOKEN )
416449 assert r .code == 200
0 commit comments