o
    tf                     @   sz  d 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	m
Z
mZ ddl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mZ ddlmZ ddlmZmZmZmZm Z m!Z!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, G dd de%Z-G dd deZ.G dd de+eZ/G dd de/Z0G dd de/Z1G dd de0Z2G dd de2Z3d d! Z4dS )"zw
Authenticated HTTP proxy for Jupyter Notebooks

Some original inspiration from https://github.com/senko/tornado-proxy
    N)Lockcopy)mkdtemp)quoteurlparse
urlunparse)JupyterHandlerutcnow)ensure_asyncurl_path_join)SupervisedProcess)
httpclienthttputilweb)SimpleAsyncHTTPClient)BytesDictInstanceIntegerUnicodeUniondefaultobserve)	HasTraits   )UnixResolvercall_with_asked_args)WebSocketHandlerMixinpingable_ws_connectc                       s   e Zd ZdZeejdZee	 ee
jdgdZe Ze ZeddZeddd Zed	d
d Zeddd Zeddd Zeddd Z fddZdd Z  ZS )RewritableResponsezJ
    A class to hold the response to be rewritten by rewrite_response
    )klass)Ztrait_typesT)
allow_noneheadersc                 C   s   t | jjS N)r   orig_responser$   self r)   f/var/www/html/software/conda/envs/catlas/lib/python3.10/site-packages/jupyter_server_proxy/handlers.py_default_headers+   s   z#RewritableResponse._default_headersbodyc                 C      | j jS r%   )r&   r,   r'   r)   r)   r*   _default_body/      z RewritableResponse._default_bodycodec                 C   r-   r%   )r&   r0   r'   r)   r)   r*   _default_code3   r/   z RewritableResponse._default_codereasonc                 C   r-   r%   )r&   r2   r'   r)   r)   r*   _default_reason7   r/   z"RewritableResponse._default_reasonc                 C   s4   | j tj|d dkrtj|d d| _ d S d S )NoldUnknownnew)r2   r   	responsesget)r(   Zchanger)   r)   r*   _observe_code;   s   
z RewritableResponse._observe_codec                    s   t  j|i | | j d S r%   )super__init__r0   r(   argskwargs	__class__r)   r*   r;   H   s   
zRewritableResponse.__init__c                 C   s   t | }|| |S )zI
        Apply a function to a copy of self, and return the copy
        r   )r(   funcr6   r)   r)   r*   _apply_to_copyN   s   z!RewritableResponse._apply_to_copy)__name__
__module____qualname____doc__r   r   HTTPResponser&   r   r   r   HTTPHeadersr$   r   r,   r   r0   r   r2   r   r+   r.   r1   r3   r   r9   r;   rB   __classcell__r)   r)   r?   r*   r!      s&    





r!   c                   @   s   e Zd ZdZejdd ZdS )AddSlashHandlerz*Add trailing slash to URLs that need them.c                 G   s0   t | jj}|j|jd d}| t| d S )N/)path)r   requesturi_replacerL   redirectr   )r(   r=   srcdestr)   r)   r*   r8   Z   s   zAddSlashHandler.getN)rC   rD   rE   rF   r   authenticatedr8   r)   r)   r)   r*   rJ   W   s    rJ   c                       s
  e Zd ZdZdZ fddZd:ddZdd Z fd	d
Zd;ddZ	d;ddZ
d;ddZd;ddZd;ddZd;ddZd;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d*d+ Zd,d- Zd;d.d/Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Z  Z S )<ProxyHandlera  
    A tornado request handler that proxies HTTP and websockets from
    a given host/port combination. This class is not meant to be
    used directly as a means of overriding CORS. This presents significant
    security risks, and could allow arbitrary remote code access. Instead, it is
    meant to be subclassed and used for proxying URLs from trusted sources.

    Subclasses should implement open, http_get, post, put, delete, head, patch,
    and options.
    Nc                    sR   d| _ |dd| _|dddg| _|dt | _d | _t j|i | d S )N absolute_urlFhost_allowlist	localhostz	127.0.0.1rewrite_response)	
proxy_basepoprV   rW   tuplerY   _requested_subprotocolsr:   r;   r<   r?   r)   r*   r;   o   s   zProxyHandler.__init__c                 C   s   t | |S r%   )r	   check_origin)r(   originr)   r)   r*   r^   }      zProxyHandler.check_originc                    
   t d)Nz0Subclasses of ProxyHandler should implement openNotImplementedErrorr(   portproxied_pathr)   r)   r*   open   s   zProxyHandler.openc                    st   t  j|i |}|dur|I dH  | jjdkr/| jjdd dkr/| js-t	ddS t
dd |  dS )	z
        Enforce authentication on *all* requests.

        This method is called *before* any other method for all requests.
        See https://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.prepare.
        NGETUpgraderU   	websocket  c                 S   s   d S r%   r)   )Zrequest_handlerr)   r)   r*   <lambda>       z&ProxyHandler.prepare.<locals>.<lambda>)r:   preparerM   methodr$   r8   lowercurrent_userr   	HTTPErrorrS   )r(   r=   r>   Z	_preparedr?   r)   r*   rn      s   

zProxyHandler.preparerU   c                    ra   )zOur non-websocket GET.z4Subclasses of ProxyHandler should implement http_getrb   r(   hostre   
proxy_pathr)   r)   r*   http_get   s   zProxyHandler.http_getc                 C      t d)Nz5Subclasses of ProxyHandler should implement this postrb   rs   r)   r)   r*   post      zProxyHandler.postc                 C   rw   )Nz4Subclasses of ProxyHandler should implement this putrb   )r(   re   ru   r)   r)   r*   put   ry   zProxyHandler.putc                 C   rw   )Nz2Subclasses of ProxyHandler should implement deleterb   rs   r)   r)   r*   delete      zProxyHandler.deletec                 C   rw   )Nz0Subclasses of ProxyHandler should implement headrb   rs   r)   r)   r*   head   r|   zProxyHandler.headc                 C   rw   )Nz1Subclasses of ProxyHandler should implement patchrb   rs   r)   r)   r*   patch   r|   zProxyHandler.patchc                 C   rw   )Nz3Subclasses of ProxyHandler should implement optionsrb   rs   r)   r)   r*   options   r|   zProxyHandler.optionsc                 C   s0   |    t| dr| jj|t|td dS dS )zh
        Called when we receive a message from our client.

        We proxy it to the backend.
        wsbinaryN)_record_activityhasattrr   write_message
isinstancebytes)r(   messager)   r)   r*   
on_message   s   
zProxyHandler.on_messagec                 C   s:   | j d|  |   t| dr| jj| dS dS )zm
        Called when the client pings our websocket connection.

        We proxy it to the backend.
        zjupyter_server_proxy: on_ping: r   N)logdebugr   r   r   protocolZ
write_pingr(   datar)   r)   r*   on_ping   s
   
zProxyHandler.on_pingc                 C   s   | j d|  dS )z5
        Called when we receive a ping back.
        zjupyter_server_proxy: on_pong: N)r   r   r   r)   r)   r*   on_pong   s   zProxyHandler.on_pongc                 C   s   t | dr| j  dS dS )z~
        Called when the client closes our websocket connection.

        We close our connection to the backend too.
        r   N)r   r   closer'   r)   r)   r*   on_close   s   
zProxyHandler.on_closec                 C   s   t  | jd< dS )zRecord proxied activity as API activity

        avoids proxied traffic being ignored by the notebook's
        internal idle-shutdown mechanism
        Zapi_last_activityN)r
   settingsr'   r)   r)   r*   r      s   zProxyHandler._record_activityc                 C   sX   |dkrt |n|d t | }| jrt| j| jS | jr%t| jdd|S t| jd|S )a5  
        Some applications need to know where they are being proxied from.
        This is either:
        - {base_url}/proxy/{port}
        - {base_url}/proxy/{host}:{port}
        - {base_url}/proxy/absolute/{port}
        - {base_url}/proxy/absolute/{host}:{port}
        - {base_url}/{proxy_base}
        rX   :proxyabsolute)strrZ   r   base_urlrV   )r(   rt   re   Zhost_and_portr)   r)   r*   _get_context_path   s    
zProxyHandler._get_context_pathc                 C   sn   | j r| ||}t||}n|}|dsd| }t|dd}dj||||d}| jjr5|d| jj 7 }|S )NrK   z:/?#[]@!$&'()*+,;=-._~)safez {protocol}://{host}:{port}{path})r   rt   re   rL   ?)rV   r   r   
startswithr   formatrM   query)r(   r   rt   re   rf   context_pathZclient_path
client_urir)   r)   r*   get_client_uri  s    
	zProxyHandler.get_client_uric           	      C   sj   |   }| d|||}| js!| ||}||d< ||d< ||d< tj|f| jj|d|d|  }|S )NhttpzX-Forwarded-ContextzX-ProxyContextPathzX-Forwarded-PrefixF)ro   r,   Zdecompress_responser$   )	proxy_request_headersr   rV   r   r   HTTPRequestrM   ro   proxy_request_options)	r(   rt   re   rf   r,   r$   r   r   reqr)   r)   r*   _build_proxy_request   s$   z!ProxyHandler._build_proxy_requestc                 C   s    t | jr| | |S || jv S r%   )callablerW   )r(   rt   r)   r)   r*   _check_host_allowlist7  s   

z"ProxyHandler._check_host_allowlistc              
      s\  |  |stdd| dg d}|D ]}|| jjv r#| jj|= q|   | jjdd dkr?| j	d | 
d	 | jj}|sP| jjd
v rNd}nd}| jduro| jd| j |dkseJ dtdt| jd}nt }| ||||}| jd|j  z|j|ddI dH }	W n tjy }
 z|
jdkr|   tdt|
 d}
~
ww |   |	jrt|	jtjurtd	t|	jt|	d}| j}t|ttfr|}n|g}| j||||d |}|D ]dtf fdd}||}q| 
|j|j  t!" | _#|j$ D ]\}}|dvr| %|| q|jr,| &|j dS dS )z
        This serverextension handles:
            {base_url}/proxy/{port([0-9]+)}/{proxied_path}
            {base_url}/proxy/absolute/{port([0-9]+)}/{proxied_path}
            {base_url}/{proxy_base}/{proxied_path}
        rk   zHost 'zp' is not allowed. See https://jupyter-server-proxy.readthedocs.io/en/latest/arbitrary-ports-hosts.html for info.)	zProxy-Connectionz
Keep-AliveTransfer-EncodingZTE
ConnectionZTrailerri   zProxy-AuthorizationzProxy-Authenticateri   rU   rj   z=we wanna websocket, but we don't define WebSocketProxyHandler  >   PUTPOST    Nz Making client for Unix socket %rrX   'Unix sockets only possible on localhostT)Zforce_instanceresolverzProxying request to F)Zraise_erroriW  )r&   )rM   r&   rt   re   rL   rewritable_responsec                    s   t d| i S )Nresponser   )r   Z!optional_args_to_rewrite_functionZrewriter)   r*   
rewrite_pe  s   z&ProxyHandler.proxy.<locals>.rewrite_pe)zContent-Lengthr   r   )'r   r   rr   rM   r$   r   r8   rp   r   info
set_statusr,   ro   unix_socketr   r   r   r   ZAsyncHTTPClientr   urlfetchr0   r   errortyper!   rY   r   listr\   rB   r2   r   rH   _headersget_all
add_headerwrite)r(   rt   re   rf   Zhop_by_hop_headersZheader_to_remover,   clientr   r   erroriginal_responserY   Zrewrite_responsesZrewritten_responser   headervr)   r   r*   r   =  s   

	





	

zProxyHandler.proxyc                    s    |sd jdj|d   dS |ds$d| }jdur>|dks1J djd| t	jnd
d	|||  fd
dfdd fdd}| I dH  dS )z
        Called when a client opens a websocket connection.

        We establish a websocket connection to the proxied backend &
        set up a callback to relay messages through.
        rk   z|Host '{host}' is not allowed. See https://jupyter-server-proxy.readthedocs.io/en/latest/arbitrary-ports-hosts.html for info.)rt   NrK   rX   r   z#Opening websocket on Unix socket %rr   c                    s4       | du r   dS  j| t| td dS )zz
            Callback when the backend sends messages to us

            We just pass it back to the frontend
            Nr   )r   r   r   r   r   )r   r'   r)   r*   
message_cb  s   z+ProxyHandler.proxy_open.<locals>.message_cbc                    s        |  dS )zy
            Callback when the backend sends pings to us.

            We just pass it back to the frontend.
            N)r   Zping)r   r'   r)   r*   ping_cb  s   z(ProxyHandler.proxy_open.<locals>.ping_cbc               	      s   j d     tj d} t| jdI d H _  j d   jjjkrMj 	djj dj dj d d S d S )	Nz,Trying to establish websocket connection to )r   r$   )rM   Zon_message_callbackZon_ping_callbacksubprotocolsr   z$Websocket connection established to z,Websocket subprotocol between proxy/server (z*) became different than for client/proxy (zd) due to https://github.com/jupyterhub/jupyter-server-proxy/issues/459. Requested subprotocols were .)
r   r   r   r   r   r    r]   r   Zselected_subprotocolwarn)rM   r   r$   r   r   r   r(   r)   r*   start_websocket_connection  s,   z;ProxyHandler.proxy_open.<locals>.start_websocket_connection)r   r   r   r   r   r   r   r   r   r   r   r   )r(   rt   re   rf   r   r)   r   r*   
proxy_open  s0   



	zProxyHandler.proxy_openc                 C   s   | j j }||   |S )z}A dictionary of headers to be used when constructing
        a tornado.httpclient.HTTPRequest instance for the proxy request.)rM   r$   r   updateget_request_headers_override)r(   r$   r)   r)   r*   r     s   z"ProxyHandler.proxy_request_headersc                 C      i S )zCAdd additional request headers. Typically overridden in subclasses.r)   r'   r)   r)   r*   r   $  s   z)ProxyHandler.get_request_headers_overridec                 C   s   t ddddS )z}A dictionary of options to be used when constructing
        a tornado.httpclient.HTTPRequest instance for the proxy request.Fg     @o@g     r@)Zfollow_redirectsconnect_timeoutrequest_timeout)dictr'   r)   r)   r*   r   (  s   z"ProxyHandler.proxy_request_optionsc                 C      dS )zi
        http://www.tornadoweb.org/en/stable/guide/security.html

        Defer to proxied apps.
        Nr)   r'   r)   r)   r*   check_xsrf_cookie/  rm   zProxyHandler.check_xsrf_cookiec                 C   s2   |r|nd| _ |r| jd| d |d S dS )a  
        Select a single Sec-WebSocket-Protocol during handshake.

        Overrides `tornado.websocket.WebSocketHandler.select_subprotocol` that
        includes an informative docstring:
        https://github.com/tornadoweb/tornado/blob/v6.4.0/tornado/websocket.py#L337-L360.
        NzClient sent subprotocols: z, selecting the firstr   )r]   r   r   )r(   r   r)   r)   r*   select_subprotocol6  s   
	zProxyHandler.select_subprotocolr%   )rU   )!rC   rD   rE   rF   r   r;   r^   rg   rn   rv   rx   rz   r{   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rI   r)   r)   r?   r*   rT   a   s>    

!






	 
QrT   c                       `   e Zd Z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 fddZ  ZS )LocalProxyHandleraN  
    A tornado request handler that proxies HTTP and websockets
    from a port on the local system. Same as the above ProxyHandler,
    but specific to 'localhost'.

    The arguments "port" and "proxied_path" in each method are extracted from
    the URL as capture groups in the regex specified in the add_handlers
    method.
    c                    s   |  ||I d H S r%   r   rd   r)   r)   r*   rv   ^  s   zLocalProxyHandler.http_getc                    s   |  d||I d H S NrX   r   rd   r)   r)   r*   rg   a     zLocalProxyHandler.openc                 C      |  ||S r%   r   rd   r)   r)   r*   rx   d  r`   zLocalProxyHandler.postc                 C   r   r%   r   rd   r)   r)   r*   rz   g  r`   zLocalProxyHandler.putc                 C   r   r%   r   rd   r)   r)   r*   r{   j  r`   zLocalProxyHandler.deletec                 C   r   r%   r   rd   r)   r)   r*   r}   m  r`   zLocalProxyHandler.headc                 C   r   r%   r   rd   r)   r)   r*   r~   p  r`   zLocalProxyHandler.patchc                 C   r   r%   r   rd   r)   r)   r*   r   s  r`   zLocalProxyHandler.optionsc                    s   t  d||S r   r:   r   rd   r?   r)   r*   r   v     zLocalProxyHandler.proxy)rC   rD   rE   rF   rv   rg   rx   rz   r{   r}   r~   r   r   rI   r)   r)   r?   r*   r   S  s    
r   c                       r   )RemoteProxyHandlera  
    A tornado request handler that proxies HTTP and websockets
    from a port on a specified remote system.

    The arguments "host", "port" and "proxied_path" in each method are
    extracted from the URL as capture groups in the regex specified in the
    add_handlers method.
    c                       |  |||I d H S r%   r   r(   rt   re   rf   r)   r)   r*   rv     r   zRemoteProxyHandler.http_getc                 C      |  |||S r%   r   r   r)   r)   r*   rx        zRemoteProxyHandler.postc                 C   r   r%   r   r   r)   r)   r*   rz     r   zRemoteProxyHandler.putc                 C   r   r%   r   r   r)   r)   r*   r{     r   zRemoteProxyHandler.deletec                 C   r   r%   r   r   r)   r)   r*   r}     r   zRemoteProxyHandler.headc                 C   r   r%   r   r   r)   r)   r*   r~     r   zRemoteProxyHandler.patchc                 C   r   r%   r   r   r)   r)   r*   r     r   zRemoteProxyHandler.optionsc                    r   r%   r   r   r)   r)   r*   rg     r   zRemoteProxyHandler.openc                    s   t  |||S r%   r   r   r?   r)   r*   r     r   zRemoteProxyHandler.proxy)rC   rD   rE   rF   rv   rx   rz   r{   r}   r~   r   rg   r   rI   r)   r)   r?   r*   r   z  s    	r   c                       s   e Zd ZdZdZi Zedd Zdd Zdd Z	 fd	d
Z
dd Z fddZdd Zdd Zdd Zdd Zdd Zdd Z  ZS )NamedLocalProxyHandlera^  
    A tornado request handler that proxies HTTP and websockets from a port on
    the local system. The port is specified in config, and associated with a
    name which forms part of the URL.

    Config will create a subclass of this for each named proxy. A further
    subclass below is used for named proxies where we also start the server.
    r   c                 C   s   | j | jpd| jdS )NrU   re   r   r   r   r'   r)   r)   r*   process_args  s   z#NamedLocalProxyHandler.process_argsc                    st    j }t|tu r|jdi |S t|tu r  fdd|D S t|tu r1 fdd| D S tdt| )Nc                    s   g | ]}  |qS r)   _render_template).0r   r'   r)   r*   
<listcomp>  s    z;NamedLocalProxyHandler._render_template.<locals>.<listcomp>c                    s"   i | ]\}}  |  |qS r)   r   )r   kr   r'   r)   r*   
<dictcomp>  s    z;NamedLocalProxyHandler._render_template.<locals>.<dictcomp>zValue of unrecognized type r)   )r   r   r   r   r   r   items
ValueError)r(   valuer=   r)   r'   r*   r     s   
z'NamedLocalProxyHandler._render_templatec                 C   s   t |r
t|| j}| |S )z5Call any callables, then render any templated values.)r   r   r   r   )r(   	attributer)   r)   r*   _realize_rendered_template  s   
z1NamedLocalProxyHandler._realize_rendered_templatec                    s\   | ds
d| }| jr"t| jrt| jd|i}n| j||}tt ||I d H S )NrK   rL   )r   mappathr   r   r8   r   r:   r   r(   re   rL   r?   r)   r*   r     s   

zNamedLocalProxyHandler.proxyc                    s   t | | j|I d H S r%   )r   r   re   r(   rL   r)   r)   r*   rv     s   zNamedLocalProxyHandler.http_getc                    s   t  | j|I d H S r%   )r:   rg   re   r   r?   r)   r*   rg     s   zNamedLocalProxyHandler.openc                 C      |  | j|S r%   r   re   r   r)   r)   r*   rx     r   zNamedLocalProxyHandler.postc                 C   r   r%   r   r   r)   r)   r*   rz     r   zNamedLocalProxyHandler.putc                 C   r   r%   r   r   r)   r)   r*   r{     r   zNamedLocalProxyHandler.deletec                 C   r   r%   r   r   r)   r)   r*   r}     r   zNamedLocalProxyHandler.headc                 C   r   r%   r   r   r)   r)   r*   r~     r   zNamedLocalProxyHandler.patchc                 C   r   r%   r   r   r)   r)   r*   r     r   zNamedLocalProxyHandler.options)rC   rD   rE   rF   re   r   propertyr   r   r   r   rv   rg   rx   rz   r{   r}   r~   r   rI   r)   r)   r?   r*   r     s"    	
r   c                       s   e Zd ZdZ fddZdd ZdZedd Zed	d
 Z	dd Z
dd Zdd Zdd Zdd Zdd Z fddZ fddZ  ZS )SuperviseAndProxyHandlera  
    A tornado request handler that proxies HTTP and websockets from a local
    process which is launched on demand to handle requests. The command and
    other process options are specified in config.

    A subclass of this will be made for each configured server process.
    c                    s0   d| _ d| _i | _t | _t j|i | d S )Nr   F)requested_portrequested_unix_socketr   r   commandr:   r;   r<   r?   r)   r*   r;     s
   z!SuperviseAndProxyHandler.__init__c                 C   s    || _ d|vrt |d< d S d S )N	proc_lock)stater   )r(   r   r)   r)   r*   
initialize  s   z#SuperviseAndProxyHandler.initializeprocessc                 C   sd   | j rdS d| jvr-| jr| j| jd< nt }|d| jf | d | jd< |  | jd S )zj
        Allocate either the requested port or a random empty port for use by
        application
        r   re   rU   r   )r   r   r   socketbindgetsocknamer   )r(   sockr)   r)   r*   re     s   

zSuperviseAndProxyHandler.portc                 C   sT   d| j vr%| jdu rtdd}tj|d}n	| jr| j}nd }|| j d< | j d S )Nr   Tzjupyter-server-proxy-)prefixr  )r   r   r   osrL   join)r(   Zsock_dirZ	sock_pathr)   r)   r*   r     s   




z$SuperviseAndProxyHandler.unix_socketc                 C   s   |  | jS r%   )r   r   r'   r)   r)   r*   get_cmd&  r`   z SuperviseAndProxyHandler.get_cmdc                 C   s   t  S )zGet the current working directory for our process

        Override in subclass to launch the process in a directory
        other than the current.
        )r  getcwdr'   r)   r)   r*   get_cwd)  s   z SuperviseAndProxyHandler.get_cwdc                 C   r   )z[Set up extra environment variables for process. Typically
        overridden in subclasses.r)   r'   r)   r)   r*   get_env1  s   z SuperviseAndProxyHandler.get_envc                 C   r   )zU
        Return timeout (in s) to wait before giving up on process readiness
           r)   r'   r)   r)   r*   get_timeout6  s   z$SuperviseAndProxyHandler.get_timeoutc              
      s*  | j d urd}t| j }nd| j }d }tj|d4 I d H g}z<|j|dd4 I d H $}| jd|j d|  	 W d   I d H  W W d   I d H  dS 1 I d H sXw   Y  W n tj	y|   | jd	| d
 Y W d   I d H  dS w W d   I d H  d S 1 I d H sw   Y  d S )Nzhttp://localhostzhttp://localhost:)	connectorF)allow_redirectsz	Got code z back from TzConnection to z refused)
r   aiohttpZUnixConnectorre   ZClientSessionr8   r   r   statusZClientConnectionError)r(   pr   r  sessionrespr)   r)   r*   _http_ready_func<  s*   
.z)SuperviseAndProxyHandler._http_ready_funcc              	      s:  | j d 4 I dH  d| j vrz|  }|s'd| j d< 	 W d  I dH  dS tj }||   |  }t| j	g|R || j
|| jd}|| j d< z$| I dH  | I dH }|sp| I dH  tdd| j	 dW n   | j d=  W d  I dH  dS W d  I dH  dS 1 I dH sw   Y  dS )	z#
        Start the process
        r   Nprocz+process not managed by jupyter-server-proxy)envZ
ready_funcZready_timeoutr   r   zcould not start z in time)r   r	  r  environr   r   r  r  r   namer  r   startreadykillr   rr   )r(   cmdZ
server_envtimeoutr  Zis_readyr)   r)   r*   ensure_processN  sH   



".z'SuperviseAndProxyHandler.ensure_processc                    s(   |   I d H  tt ||I d H S r%   )r   r   r:   r   r   r?   r)   r*   r     s   zSuperviseAndProxyHandler.proxyc                    s"   |   I d H  t |I d H S r%   )r   r:   rg   r   r?   r)   r*   rg     s   zSuperviseAndProxyHandler.open)rC   rD   rE   rF   r;   r   r  r   re   r   r	  r  r  r  r  r   r   rg   rI   r)   r)   r?   r*   r     s"    

2r   c                 C   s   |j }|j}| dt| jd dtd||dft| jd dtd||dft| jd dtd|d	ft| jd d
td|d	fg d S )Nz.*r   z/proxy/([^/:@]+):(\d+)(/.*|)F)rV   rW   rY   z%/proxy/absolute/([^/:@]+):(\d+)(/.*|)Tz/proxy/(\d+)(/.*|))rV   rY   z/proxy/absolute/(\d+)(/.*|))rW   Znon_service_rewrite_responseadd_handlersr   r   r   r   )Zweb_appZserverproxy_configrW   rY   r)   r)   r*   setup_handlers  sX   r"  )5rF   r  r  asyncior   r   tempfiler   urllib.parser   r   r   r  Zjupyter_server.base.handlersr	   r
   Zjupyter_server.utilsr   r   Zsimpervisorr   tornador   r   r   Ztornado.simple_httpclientr   Z	traitletsr   r   r   r   r   r   r   r   Ztraitlets.traitletsr   Zunixsockr   utilsr   rj   r   r    r!   rJ   rT   r   r   r   r   r"  r)   r)   r)   r*   <module>   s<    (;
   u'&N 