
    g&                    (   U d dl mZ d dlZd dlZd dlmZmZmZ d dlm	Z	 d dl
Zd dlZd dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZmZ d dlmZ d dlm Z m!Z!m"Z" erd dl#m$Z$ d dl%m&Z&  ee'      Z(de)d<    G d dee      Z*y)    )annotationsN)TYPE_CHECKINGAnyFinal)urlparse)utf8)WebSocketHandler)config)
get_logger)BackMsg)RuntimeSessionClientSessionClientDisconnectedError)serialize_forward_msg)AUTH_COOKIE_NAMEis_url_from_allowed_originsis_xsrf_enabled)	Awaitable)
ForwardMsgr   _LOGGERc                       e Zd ZdZddZ	 	 	 d	 	 	 	 	 	 	 	 	 d fdZd fdZddZddZddZ	ddZ
dd	Zdd
ZddZddZ xZS )BrowserWebSocketHandlerz/Handles a WebSocket connection from the browserc                N    || _         d | _        t               r| j                  }y y N)_runtime_session_idr   
xsrf_token)selfruntime_s      c/var/www/openai/venv/lib/python3.12/site-packages/streamlit/web/server/browser_websocket_handler.py
initializez"BrowserWebSocketHandler.initialize4   s'    '+ A     c                l    	 t         |   ||||      S # t        $ r t         |   ||||      cY S w xY w)zGet a signed cookie from the request. Added for compatibility with
        Tornado < 6.3.0.
        See release notes: https://www.tornadoweb.org/en/stable/releases/v6.3.0.html#deprecation-notices
        )superget_signed_cookieAttributeErrorget_secure_cookie)r   namevaluemax_age_daysmin_version	__class__s        r!   r&   z)BrowserWebSocketHandler.get_signed_cookie?   sF    	U7,T5,TT 	U7,T5,TT	Us    33c                <    t         |   |      xs t        |      S )zSet up CORS.)r%   check_originr   )r   originr-   s     r!   r/   z$BrowserWebSocketHandler.check_originO   s    w#F+R/J6/RRr#   c                    | j                  |      \  }}}| j                         \  }}}t        |      }t        |      }|r|syt        j                  ||      S )zInspired by tornado.web.RequestHandler.check_xsrf_cookie method,
        to check the XSRF token passed in Websocket connection header.
        F)_decode_xsrf_token_get_raw_xsrf_tokenr   hmaccompare_digest)r   supplied_tokenr    tokenexpected_tokendecoded_tokendecoded_expected_tokens          r!   _validate_xsrf_tokenz,BrowserWebSocketHandler._validate_xsrf_tokenS   s`     --n=5!#779>1U!%n!5$:""=2HIIr#   c                6   t        j                  |      }i }|j                  dd      }t        | j                  j
                  d         }|j                  dz   |j                  z   }||k(  r,|j                  dd      |d<   |d= |d= |j                  |       |S )zProcess the user cookie and extract the user info after
        validating the origin. Origin is validated for security reasons.
        r0   NOriginz://is_logged_inF)	jsonloadsgetr   requestheadersschemenetlocupdate)r   raw_cookie_valuecookie_value	user_infocookie_value_originparsed_origin_from_headerexpected_origin_values          r!   _parse_user_cookiez*BrowserWebSocketHandler._parse_user_cookiea   s     zz"23	*..x>$,T\\-A-A(-K$L!%,,u47P7W7WW 	 "77(4(8(8(OIn%X&^,\*r#   c                    	 | j                  t        |      d       y# t        j                  j                  $ r}t
        |d}~ww xY w)z!Send a ForwardMsg to the browser.T)binaryN)write_messager   tornado	websocketWebSocketClosedErrorr   )r   msges      r!   write_forward_msgz)BrowserWebSocketHandler.write_forward_msgu   sD    	84S9$G  55 	80a7	8s    AAAc                    |r|d   S y)a  Return the first subprotocol in the given list.

        This method is used by Tornado to select a protocol when the
        Sec-WebSocket-Protocol header is set in an HTTP Upgrade request.

        NOTE: We repurpose the Sec-WebSocket-Protocol header here in a slightly
        unfortunate (but necessary) way. The browser WebSocket API doesn't allow us to
        set arbitrary HTTP headers, and this header is the only one where we have the
        ability to set it to arbitrary values, so we use it to pass tokens (in this
        case, the previous session ID to allow us to reconnect to it) from client to
        server as the *third* value in the list.

        The reason why the auth token is set as the third value is that:
          - when Sec-WebSocket-Protocol is set, many clients expect the server to
            respond with a selected subprotocol to use. We don't want that reply to be
            the session token, so we by convention have the client always set the first
            protocol to "streamlit" and select that.
          - the second protocol in the list is reserved in some deployment environments
            for an auth token that we currently don't use
        r   N )r   subprotocolss     r!   select_subprotocolz*BrowserWebSocketHandler.select_subprotocol|   s    * ?"r#   c                   i }d }	 | j                   j                  d   j                  d      D cg c]  }|j                          }}| j	                  t
              }t               r8|r6|d   }| j                  |      r |j                  | j                  |             t        |      dk\  r|d   }| j                  j                  | ||      | _        y c c}w # t        $ r Y 4w xY w)NzSec-Websocket-Protocol,         )clientrI   existing_session_id)rB   rC   splitstripr&   r   r   r;   rF   rM   lenKeyErrorr   connect_sessionr   )	r   argskwargsrI   ra   pws_protocolsrG   csrf_protocol_values	            r!   openzBrowserWebSocketHandler.open   s   24	"	 --.FGMMcRRA 	R  
  $556FG %5&21o#,,-@A$$T%<%<=M%NO< A% '31o#  ==88 3 9 

 5   	 	s#   *C CA,C C 	C('C(c                v    | j                   sy | j                  j                  | j                          d | _         y r   )r   r   disconnect_sessionr   s    r!   on_closez BrowserWebSocketHandler.on_close   s.    (()9)9:r#   c                2    t        j                  d      ri S y)zEnable WebSocket compression.

        Returning an empty dict enables websocket compression. Returning
        None disables it.

        (See the docstring in the parent class.)
        z!server.enableWebsocketCompressionN)r
   
get_optionro   s    r!   get_compression_optionsz/BrowserWebSocketHandler.get_compression_options   s     @AIr#   c                N   | j                   sy 	 t        |t              rt        d      t	               }|j                  |       t        j                  d|       |j                  d      dk(  rQt        j                  d      st        j                  d      r| j                          y t        j!                  d       y |j                  d      d	k(  r[t        j                  d      st        j                  d      r| j                  j#                          y t        j!                  d
       y | j                  j%                  | j                   |       y # t        $ rE}t        j                  d       | j                  j                  | j                   |       Y d }~y d }~ww xY w)NzIWebSocket received an unexpected `str` message. (We expect `bytes` only.)z'Received the following back message:
%sz Error deserializing back messagetypedebug_disconnect_websocketzglobal.developmentModezglobal.e2eTestzQClient tried to disconnect websocket when not in development mode or e2e testing.debug_shutdown_runtimezNClient tried to shut down runtime when not in development mode or e2e testing.)r   
isinstancestrRuntimeErrorr   ParseFromStringr   debug	Exception	exceptionr   (handle_backmsg_deserialization_exception
WhichOneofr
   rr   closewarningstophandle_backmsg)r   payloadrT   exs       r!   
on_messagez"BrowserWebSocketHandler.on_message   sS   	'3' #0 
 )C(MMDcJ >>&!%AA  !9:f>O>O ? 

g ^^F#'??  !9:f>O>O ? ""$d
 MM(()9)93?9  	@AMMBB4CSCSUWX	s   AE 	F$;FF$)r   r   returnNone)N   N)
r)   ry   r*   
str | Noner+   floatr,   z
int | Noner   zbytes | None)r0   ry   r   bool)r6   ry   r   r   )rG   bytesr   zdict[str, Any])rT   r   r   r   )rY   z	list[str]r   r   )r   zAwaitable[None] | None)r   r   )r   zdict[Any, Any] | None)r   zstr | bytesr   r   )__name__
__module____qualname____doc__r"   r&   r/   r;   rM   rV   rZ   rl   rp   rs   r   __classcell__)r-   s   @r!   r   r   1   s    9	  ! "&UU U 	U
  U 
U SJ(84B 
-@r#   r   )+
__future__r   r4   r?   typingr   r   r   urllib.parser   tornado.concurrentrQ   tornado.lockstornado.netutiltornado.webtornado.websockettornado.escaper   r	   	streamlitr
   streamlit.loggerr   streamlit.proto.BackMsg_pb2r   streamlit.runtimer   r   r   streamlit.runtime.runtime_utilr    streamlit.web.server.server_utilr   r   r   collections.abcr   streamlit.proto.ForwardMsg_pb2r   r   r   __annotations__r   rX   r#   r!   <module>r      sw    #   , , !       .  ' / T T @  )9H% %E@. E@r#   