2828from uvicorn .logging import TRACE_LOG_LEVEL
2929from uvicorn .protocols .utils import (
3030 ClientDisconnected ,
31+ get_client_addr ,
3132 get_local_addr ,
3233 get_path_with_query_string ,
3334 get_remote_addr ,
@@ -187,14 +188,14 @@ def handle_connect(self, event: Request) -> None:
187188 raw_path , _ , query_string = event .path .partition ("?" )
188189 self .scope : WebSocketScope = {
189190 "type" : "websocket" ,
190- "asgi" : {"version" : self .config .asgi_version , "spec_version" : "2.3 " },
191+ "asgi" : {"version" : self .config .asgi_version , "spec_version" : "2.4 " },
191192 "http_version" : "1.1" ,
192193 "scheme" : self .scheme ,
193194 "server" : self .server ,
194195 "client" : self .client ,
195196 "root_path" : self .root_path ,
196- "path" : unquote (raw_path ),
197- "raw_path" : raw_path .encode ("ascii" ),
197+ "path" : self . root_path + unquote (raw_path ),
198+ "raw_path" : self . root_path . encode ( "ascii" ) + raw_path .encode ("ascii" ),
198199 "query_string" : query_string .encode ("ascii" ),
199200 "headers" : headers ,
200201 "subprotocols" : event .headers .get_all ("Sec-WebSocket-Protocol" ),
@@ -301,11 +302,11 @@ async def send(self, message: ASGISendEvent) -> None:
301302 message = cast (WebSocketAcceptEvent , message )
302303 self .logger .info (
303304 '%s - "WebSocket %s" [accepted]' ,
304- self .scope [ "client" ] ,
305+ get_client_addr ( self .scope ) ,
305306 get_path_with_query_string (self .scope ),
306307 )
307308 headers = [
308- (name .decode ("latin-1" ).lower (), value .decode ("latin-1" ). lower () )
309+ (name .decode ("latin-1" ).lower (), value .decode ("latin-1" ))
309310 for name , value in (self .default_headers + list (message .get ("headers" , [])))
310311 ]
311312 accepted_subprotocol = message .get ("subprotocol" )
@@ -324,7 +325,7 @@ async def send(self, message: ASGISendEvent) -> None:
324325 self .queue .put_nowait ({"type" : "websocket.disconnect" , "code" : 1006 })
325326 self .logger .info (
326327 '%s - "WebSocket %s" 403' ,
327- self .scope [ "client" ] ,
328+ get_client_addr ( self .scope ) ,
328329 get_path_with_query_string (self .scope ),
329330 )
330331 response = self .conn .reject (HTTPStatus .FORBIDDEN , "" )
@@ -340,7 +341,7 @@ async def send(self, message: ASGISendEvent) -> None:
340341 raise RuntimeError ("Invalid HTTP status code '%d' in response." % message ["status" ])
341342 self .logger .info (
342343 '%s - "WebSocket %s" %d' ,
343- self .scope [ "client" ] ,
344+ get_client_addr ( self .scope ) ,
344345 get_path_with_query_string (self .scope ),
345346 message ["status" ],
346347 )
@@ -363,23 +364,24 @@ async def send(self, message: ASGISendEvent) -> None:
363364 message = cast (WebSocketSendEvent , message )
364365 bytes_data = message .get ("bytes" )
365366 text_data = message .get ("text" )
366- if text_data :
367- self .conn .send_text (text_data .encode ())
368- elif bytes_data :
367+ if bytes_data is not None :
369368 self .conn .send_binary (bytes_data )
369+ elif text_data is not None :
370+ self .conn .send_text (text_data .encode ())
370371 output = self .conn .data_to_send ()
371372 self .transport .write (b"" .join (output ))
372373
373- elif message_type == "websocket.close" and not self .transport .is_closing ():
374- message = cast (WebSocketCloseEvent , message )
375- code = message .get ("code" , 1000 )
376- reason = message .get ("reason" , "" ) or ""
377- self .queue .put_nowait ({"type" : "websocket.disconnect" , "code" : code , "reason" : reason })
378- self .conn .send_close (code , reason )
379- output = self .conn .data_to_send ()
380- self .transport .write (b"" .join (output ))
381- self .close_sent = True
382- self .transport .close ()
374+ elif message_type == "websocket.close" :
375+ if not self .transport .is_closing ():
376+ message = cast (WebSocketCloseEvent , message )
377+ code = message .get ("code" , 1000 )
378+ reason = message .get ("reason" , "" ) or ""
379+ self .queue .put_nowait ({"type" : "websocket.disconnect" , "code" : code , "reason" : reason })
380+ self .conn .send_close (code , reason )
381+ output = self .conn .data_to_send ()
382+ self .transport .write (b"" .join (output ))
383+ self .close_sent = True
384+ self .transport .close ()
383385 else :
384386 msg = "Expected ASGI message 'websocket.send' or 'websocket.close', but got '%s'."
385387 raise RuntimeError (msg % message_type )
0 commit comments