File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -451,6 +451,21 @@ async def test_keepalive_timeout_with_pipelined_requests(http_protocol_cls: type
451451 assert protocol .timeout_keep_alive_task is not None
452452
453453
454+ async def test_keepalive_timeout_with_pipelined_websocket_upgrade (
455+ http_protocol_cls : type [HTTPProtocol ], ws_protocol_cls : type [WSProtocol ]
456+ ):
457+ if http_protocol_cls .__name__ == "HttpToolsProtocol" :
458+ pytest .skip ("httptools never upgrades with the keep-alive timer armed" )
459+
460+ app = Response ("Hello, world" , media_type = "text/plain" )
461+
462+ protocol = get_connected_protocol (app , http_protocol_cls , ws = ws_protocol_cls )
463+ protocol .data_received (SIMPLE_GET_REQUEST + UPGRADE_REQUEST )
464+ await protocol .loop .run_one ()
465+
466+ assert protocol .timeout_keep_alive_task is None
467+
468+
454469async def test_close (http_protocol_cls : type [HTTPProtocol ]):
455470 app = Response (b"" , status_code = 204 , headers = {"connection" : "close" })
456471
Original file line number Diff line number Diff line change @@ -197,6 +197,9 @@ def handle_events(self) -> None:
197197 break
198198
199199 elif isinstance (event , h11 .Request ):
200+ # Pipelined HTTP requests and WebSocket upgrades may be processed after the keep-alive timer is armed.
201+ self ._unset_keepalive_if_required ()
202+
200203 self .headers = [(key .lower (), value ) for key , value in event .headers ]
201204 raw_path , _ , query_string = event .target .partition (b"?" )
202205 path = unquote (raw_path .decode ("ascii" ))
@@ -231,14 +234,6 @@ def handle_events(self) -> None:
231234 else :
232235 app = self .app
233236
234- # When starting to process a request, disable the keep-alive
235- # timeout. Normally we disable this when receiving data from
236- # client and set back when finishing processing its request.
237- # However, for pipelined requests processing finishes after
238- # already receiving the next request and thus the timer may
239- # be set here, which we don't want.
240- self ._unset_keepalive_if_required ()
241-
242237 self .cycle = RequestResponseCycle (
243238 scope = self .scope ,
244239 conn = self .conn ,
Original file line number Diff line number Diff line change @@ -145,6 +145,9 @@ def data_received(self, data: bytes) -> None:
145145 def handle_events (self , event : zttp .Event ) -> None :
146146 while event is not zttp .NEED_DATA :
147147 if isinstance (event , zttp .Request ):
148+ # Pipelined HTTP requests and WebSocket upgrades may be processed after the keep-alive timer is armed.
149+ self ._unset_keepalive_if_required ()
150+
148151 assert isinstance (event .headers , zttp .HeaderBlock )
149152 self .headers = event .headers .to_list (lowercase_names = True )
150153 path = event .path .decode ("ascii" )
@@ -181,8 +184,6 @@ def handle_events(self, event: zttp.Event) -> None:
181184 else :
182185 app = self .app
183186
184- self ._unset_keepalive_if_required ()
185-
186187 self .cycle = RequestResponseCycle (
187188 scope = self .scope ,
188189 conn = self .conn ,
You can’t perform that action at this time.
0 commit comments