o
    i|-                     @   sJ  d 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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 dd
lmZmZ ddlmZ ddlmZmZ ddl m!Z! ddl"m#Z# e$e%ddZ&G dd deeZ'G dd deZ(G dd deZ)ddl*m+Z+ ddl,m-Z- de+ e'fde- e)fgZ.dS )zGateway API handlers.    N)Optionalcast)Session)web)Future)json_decode
url_escapeutf8)HTTPRequest)IOLoopPeriodicCallback)WebSocketHandlerwebsocket_connect)LoggingConfigurable   )
APIHandlerJupyterHandler)url_path_join   )GatewayClientGATEWAY_WS_PING_INTERVAL_SECS   c                       s   e Zd ZdZdZdZdZdZdddZdd Z	dd Z
d	d
 Zdd Z fddZdd Zdd Zdd Zd fdd	Z fddZedd Z  ZS )WebSocketChannelsHandlerz$Gateway web socket channels handler.Nc                 C   s   t | |S )zCheck origin for the socket.)r   check_origin)selforigin r   Z/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/jupyter_server/gateway/handlers.pyr   $      z%WebSocketChannelsHandler.check_originc                 C   s   dS )zVUndo the set_default_headers in JupyterHandler which doesn't make sense for websocketsNr   r   r   r   r   set_default_headers(   s   z,WebSocketChannelsHandler.set_default_headersc                 C   s   i S )z+Get the compression options for the socket.r   r   r   r   r   get_compression_options,   s   z0WebSocketChannelsHandler.get_compression_optionsc                 C   s\   | j du r| jd td| ddr&| jdusJ | d| j_dS | jd dS )zRun before finishing the GET request

        Extend this method to add logic that should fire before
        the websocket finishes completing.
        Nz*Couldn't authenticate WebSocket connectioni  
session_idzNo session ID specified)current_userlogwarningr   	HTTPErrorget_argumentsessionr   r   r   r   authenticate1   s   

z%WebSocketChannelsHandler.authenticatec                 C   s6   | j d| jj t| jd| _tt	 j
d| _dS )zIntialize the socket.z$Initializing websocket connection %s)config)gateway_urlN)r$   debugrequestpathr   r*   r(   GatewayWebSocketClientr   instanceurlgatewayr   r   r   r   
initializeB   s   z#WebSocketChannelsHandler.initializec                    s4   |    || _||d< t j|i |I dH  dS )zGet the socket.	kernel_idN)r)   r4   supergetr   r4   argskwargs	__class__r   r   r6   H   s
   zWebSocketChannelsHandler.getc                 C   s0   | j du r| jdur| j  dS | d dS )zSend a ping to the socket.N    )ws_connectionping_callbackstoppingr   r   r   r   	send_pingO   s   
z"WebSocketChannelsHandler.send_pingc                 O   sF   t | jtd | _| j  | jdusJ | jj|| j|  d dS )z_Handle web socket connection open to notebook server and delegate to gateway web socket handleri  N)r4   message_callbackcompression_options)	r   rA   r   r>   startr2   on_openwrite_messager!   r7   r   r   r   openW   s   

zWebSocketChannelsHandler.openc                 C   s   | j dusJ | j | dS )z.Forward message to gateway web socket handler.N)r2   
on_message)r   messager   r   r   rH   c   s   z#WebSocketChannelsHandler.on_messageFc                    sb   | j rt|tr
d}t j||d dS | jtjr/t	
tt|}| jd| dS dS )zdSend message back to notebook client.  This is called via callback from self.gateway._read_messages.T)binaryzANotebook client closed websocket connection - message dropped: {}N)r=   
isinstancebytesr5   rF   r$   isEnabledForloggingDEBUGr   _get_message_summaryr   r	   r,   format)r   rI   rJ   msg_summaryr:   r   r   rF   h   s   
z&WebSocketChannelsHandler.write_messagec                    s8   | j d| jj | jdusJ | j  t   dS )zHandle a closing socket.zClosing websocket connection %sN)r$   r,   r-   r.   r2   on_closer5   r   r:   r   r   rS   v   s   
z!WebSocketChannelsHandler.on_closec                 C   s   g }| d }| d|  |dkr| d| d d  n |dkr:| d| d d	 | d d
 | d d  n| d d|S )zGet a summary of a message.msg_typeztype: statusz, state: {}contentexecution_stateerrorz
, {}:{}:{}enameevalue	tracebackz, ... )appendrQ   join)rI   summarymessage_typer   r   r   rP   }   s   




z-WebSocketChannelsHandler._get_message_summaryN)F)__name__
__module____qualname____doc__r(   r2   r4   r>   r   r    r!   r)   r3   r6   rA   rG   rH   rF   rS   staticmethodrP   __classcell__r   r   r:   r   r      s&    
r   c                       s`   e Zd ZdZ fd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  ZS )r/   z;Proxy web socket connection to a kernel/enterprise gateway.c                    s.   t    d| _d| _t | _d| _d| _dS )z)Initialize the gateway web socket client.NFr   )r5   __init__r4   wsr   	ws_futuredisconnectedretry)r   r9   r:   r   r   rh      s   

zGatewayWebSocketClient.__init__c                    s   d_ |_tt jt jt|d}j	d|  i }t j
di |}t|fi |}ttt|_jj t }|j fdd dS )zConnect to the socket.NchannelszConnecting to c                    
     S ra   )_read_messagesfuturerB   r   r   r   <lambda>      
 z1GatewayWebSocketClient._connect.<locals>.<lambda>r   )ri   r4   r   r   r0   ws_urlkernels_endpointr   r$   infoload_connection_argsr
   r   r   r   rj   add_done_callback_connection_doner   current
add_future)r   r4   rB   ru   r9   r-   loopr   rr   r   _connect   s"   zGatewayWebSocketClient._connectc                 C   sZ   | j s| du r| | _d| _| jd| j  dS | jd| j	t
 j dS )zHandle a finished connection.Nr   zConnection is ready: ws: zWebsocket connection has been closed via client disconnect or due to error.  Kernel with ID '{}' may not be terminated on GatewayClient: {})rk   	exceptionresultri   rl   r$   r,   r%   rQ   r4   r   r0   r1   )r   futr   r   r   rz      s   
z'GatewayWebSocketClient._connection_donec                 C   sN   d| _ | jdur| j  dS | j s%| j  | jd| j   dS dS )zHandle a disconnect.TNz-_disconnect: future cancelled, disconnected: )rk   ri   closerj   donecancelr$   r,   r   r   r   r   _disconnect   s   


z"GatewayWebSocketClient._disconnectc              
      sH  | j durNd}| jsHz
| j  I dH }W n ty0 } z| jd|  W Y d}~nd}~ww |du rC| jsB| jd| j  n|| nn| j dus| js| jt	
 jk rtddd }tt	
 jd| j  t	
 j| }|  jd7  _| jd	|| jt	
 j| j t|I dH  t }|| j| j| dS dS dS )
z"Read messages from gateway server.Nz*Exception reading message from websocket: zLost connection to Gateway: 
   d   g{Gz?r   r   zKAttempting to re-establish the connection to Gateway in %s secs (%s/%s): %s)ri   rk   read_message	Exceptionr$   rX   r%   r4   rl   r   r0   gateway_retry_maxrandomrandintmingateway_retry_intervalgateway_retry_interval_maxrw   asynciosleepr   r{   spawn_callbackr~   )r   callbackrI   ejitterretry_intervalr}   r   r   r   ro      sT   

z%GatewayWebSocketClient._read_messagesc                 K   s   t  }|| j|| dS )z2Web socket connection open against gateway server.N)r   r{   r   r~   )r   r4   rB   r9   r}   r   r   r   rE      s   zGatewayWebSocketClient.on_openc                    s<   j du rt }|j fdd dS   dS )Send message to gateway server.Nc                    rn   ra   )_write_messagerp   rI   r   r   r   rs     rt   z3GatewayWebSocketClient.on_message.<locals>.<lambda>)ri   r   r{   r|   rj   r   )r   rI   r}   r   r   r   rH     s   
z!GatewayWebSocketClient.on_messagec              
   C   sh   z| j s| jdur| j| W dS W dS W dS  ty3 } z| jd|  W Y d}~dS d}~ww )r   Nz(Exception writing message to websocket: )rk   ri   rF   r   r$   rX   )r   rI   r   r   r   r   r   	  s    z%GatewayWebSocketClient._write_messagec                 C   s   |    dS )zWeb socket closed event.N)r   r   r   r   r   rS     r   zGatewayWebSocketClient.on_close)rb   rc   rd   re   rh   r~   rz   r   ro   rE   rH   r   rS   rg   r   r   r:   r   r/      s    	+r/   c                   @   s    e Zd ZdZejdddZdS )GatewayResourceHandlerzWRetrieves resources for specific kernelspec definitions from kernel/enterprise gateway.Tc                    s`   d}| j }|||I dH }|du r| jd|| n	t|d p&d}| j||d dS )z(Get a gateway resource by name and path.NzWKernelspec resource '{}' for '{}' not found.  Gateway may not support resource serving.r   z
text/plain)set_content_type)kernel_spec_managerget_kernel_spec_resourcer$   r%   rQ   	mimetypes
guess_typefinish)r   kernel_namer.   include_bodymimetypeksmkernel_spec_resr   r   r   r6     s   zGatewayResourceHandler.getN)T)rb   rc   rd   re   r   authenticatedr6   r   r   r   r   r     s    r   )_kernel_id_regex)kernel_name_regexz/api/kernels/%s/channelsz/kernelspecs/%s/(?P<path>.*))/re   r   rN   r   osr   typingr   r   jupyter_client.sessionr   tornador   tornado.concurrentr   tornado.escaper   r   r	   tornado.httpclientr
   tornado.ioloopr   r   tornado.websocketr   r   traitlets.config.configurabler   base.handlersr   r   utilsr   managersr   intgetenvr   r   r/   r   services.kernels.handlersr   services.kernelspecs.handlersr   default_handlersr   r   r   r   <module>   s8    x 

