o
    iF                     @   s@  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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mZmZmZ ddlm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$Z$ddl%m&Z& ddl'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z. ddl/m0Z0 e1dZ2da3dd Z4dd Z5G dd dej6Z7G dd de7Z8G dd de8Z9G dd de8Z:G dd de8ej;Z<d d! Z=ej>Z>G d"d# d#e8ej;Z?G d$d% d%e9Z@G d&d' d'ej6ZAG d(d) d)e8ZBG d*d+ d+ej6ZCG d,d- d-e8ZDd.ZEd/eAfd0e@fd1ej;fd2eDfgZFdS )3z.Base Tornado handlers for the notebook server.    N)	responses)Morsel)urlparse)TemplateNotFound)webgenescapehttputil)app_log)get_sys_info)Application)filefind)string_types)utcnow)combine_translations)	is_hiddenurl_path_joinurl_is_absolute
url_escapeurldecode_unix_socket_path)csp_report_uriz[^A-Za-z0-9]c                   C   s   t d u r
tt a t S N)_sys_info_cachejsondumpsr    r   r   Q/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/notebook/base/handlers.pyjson_sys_info,   s   r   c                   C   s   t  r	t  jS tS r   )r   initializedinstancelogr
   r   r   r   r   r    2   s   
r    c                   @   s   e Zd ZdZedd Zdd Zddd	Zd
d Zdd Z	dd Z
edd Zedd Zedd Zedd Zedd Zedd ZdS )AuthenticatedHandlerz,A RequestHandler with an authenticated user.c              
   C   sD   d| j di v r| j d d S ddd| j dt| jt gS )zThe default Content-Security-Policy header

        Can be overridden by defining Content-Security-Policy in settings['headers']
        Content-Security-Policyheaders; zframe-ancestors 'self'zreport-uri r   )settingsgetjoinr   base_urlr   selfr   r   r   content_security_policy;   s   z,AuthenticatedHandler.content_security_policyc                 C   s   i }d|d< | | jdi  | j|d< | D ]$\}}z| || W q ty= } z| j| W Y d }~qd }~ww d S )NnosniffzX-Content-Type-Optionsr#   r"   )	updater%   r&   r+   items
set_header	Exceptionr    debug)r*   r#   header_namevalueer   r   r   set_default_headersK   s   
z(AuthenticatedHandler.set_default_headers/Nc                 C   sj   t |}tj tjdd }t }||dd t||d< ||d< |r+||d< | 	d|
  d	S )
a  Deletes the cookie with the given name.

        Tornado's cookie handling currently (Jan 2018) stores cookies in a dict
        keyed by name, so it can only modify one cookie with a given name per
        response. The browser can store multiple cookies with the same name
        but different domains and/or paths. This method lets us clear multiple
        cookies with the same name.

        Due to limitations of the cookie protocol, you must pass the same
        path and domain to clear a cookie as were used when that cookie
        was set (but there is no way to find out on the server side
        which values were used for a given cookie).
        im  )days z""expirespathdomainz
Set-CookieN)r   
native_strdatetimer   	timedeltar   setr	   format_timestamp
add_headerOutputString)r*   namer:   r;   r9   morselr   r   r   force_clear_cookie\   s   
z'AuthenticatedHandler.force_clear_cookiec                 C   sP   | j di }|d| j}| j| j|d |r$|dkr&| | j d S d S d S )Ncookie_optionsr:   r:   r6   )r%   r&   
setdefaultr(   clear_cookiecookie_namerE   )r*   rF   r:   r   r   r   clear_login_cookieu   s   z'AuthenticatedHandler.clear_login_cookiec                 C   s   | j d u rdS | j | S )N	anonymous)login_handlerget_userr)   r   r   r   get_current_user   s   
z%AuthenticatedHandler.get_current_userc                 C   s8   | j jdkrdS | jdu st| jdsdS | j|  S )zAsk my login_handler if I should skip the origin_check

        For example: in the default LoginHandler, if a request is token-authenticated,
        origin checking should be skipped.
        OPTIONSTNshould_check_originF)requestmethodrM   hasattrrQ   r)   r   r   r   skip_check_origin   s
   z&AuthenticatedHandler.skip_check_originc                 C   s&   | j du st| j dsdS | j | S )z'Have I been authenticated with a token?Nis_token_authenticatedF)rM   rT   rV   r)   r   r   r   token_authenticated   s   z(AuthenticatedHandler.token_authenticatedc                 C   s$   t dd| jj }| jd|S )N-z	username-rJ   )non_alphanumsubrR   hostr%   r&   )r*   default_cookie_namer   r   r   rJ      s   z AuthenticatedHandler.cookie_namec                 C   s   |   }|o
|dk S )zIs a user currently logged in?rL   )rO   r*   userr   r   r   	logged_in   s   zAuthenticatedHandler.logged_inc                 C      | j ddS )z6Return the login handler for this application, if any.login_handler_classNr%   r&   r)   r   r   r   rM         z"AuthenticatedHandler.login_handlerc                 C   r`   )z4Return the login token for this application, if any.tokenNrb   r)   r   r   r   rd      rc   zAuthenticatedHandler.tokenc                 C   s    | j du rdS t| j | jS )zMay a user proceed to log in?

        This returns True if login capability is available, irrespective of
        whether the user is already logged in or not.

        NF)rM   boolget_login_availabler%   r)   r   r   r   login_available   s   
z$AuthenticatedHandler.login_available)r6   N)__name__
__module____qualname____doc__propertyr+   r5   rE   rK   rO   rU   rW   rJ   r_   rM   rd   rg   r   r   r   r   r!   8   s*    






r!   c                       s~  e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zed d! Zed"d# Zed$d% Zed&d' Zed(d) Z fd*d+Zd,d- Zd.d/ ZdEd1d2Zd3d4 Z fd5d6Zd7d8 Z fd9d:Z d;d< Z!d=d> Z"ed?d@ Z#dAdB Z$dCdD Z%  Z&S )FIPythonHandlerzwIPython-specific extensions to authenticated handling

    Mostly property shortcuts to IPython-specific settings.
    c                 C   r`   )zzWether to user bundle in template. (*.min files)

        Mainly use for development and avoid file recompilation
        ignore_minified_jsFrb   r)   r   r   r   rn      s   z!IPythonHandler.ignore_minified_jsc                 C   s   | j dd S )Nconfigrb   r)   r   r   r   ro         zIPythonHandler.configc                 C   s   t  S )z@use the IPython log by default, falling back on tornado's logger)r    r)   r   r   r   r       s   zIPythonHandler.logc                 C   s   | j di S )z2User-supplied values to supply to jinja templates.jinja_template_varsrb   r)   r   r   r   rq      rc   z"IPythonHandler.jinja_template_varsc                 C   r`   )z8The version hash to use for cache hints for static filesversion_hashr8   rb   r)   r   r   r   rr      rc   zIPythonHandler.version_hashc                 C   s*   | j dd}|rt|r|S t| j|S )Nmathjax_urlr8   )r%   r&   r   r   r(   )r*   urlr   r   r   rs      s   zIPythonHandler.mathjax_urlc                 C   r`   )Nmathjax_configzTeX-AMS-MML_HTMLorMML-full,Saferb   r)   r   r   r   ru      rp   zIPythonHandler.mathjax_configc                 C   r`   )Nr(   r6   rb   r)   r   r   r   r(      rp   zIPythonHandler.base_urlc                 C   r`   )Ndefault_urlr8   rb   r)   r   r   r   rv      rp   zIPythonHandler.default_urlc                 C   r`   )Nwebsocket_urlr8   rb   r)   r   r   r   ws_url   rp   zIPythonHandler.ws_urlc                 C   s&   | j d| jdd | jddS )NzUsing contents: %scontents_js_sourcezservices/contents)r    r1   r%   r&   r)   r   r   r   ry      s   z!IPythonHandler.contents_js_sourcec                 C   
   | j d S )Nkernel_managerr%   r)   r   r   r   r{        
zIPythonHandler.kernel_managerc                 C   rz   )Ncontents_managerr|   r)   r   r   r   r~     r}   zIPythonHandler.contents_managerc                 C   rz   )Nsession_managerr|   r)   r   r   r   r   	  r}   zIPythonHandler.session_managerc                 C   rz   )Nterminal_managerr|   r)   r   r   r   r     r}   zIPythonHandler.terminal_managerc                 C   rz   )Nkernel_spec_managerr|   r)   r   r   r   r     r}   z"IPythonHandler.kernel_spec_managerc                 C   rz   )Nconfig_managerr|   r)   r   r   r   r     r}   zIPythonHandler.config_managerc                 C   r`   )z"Normal Access-Control-Allow-Originallow_originr8   rb   r)   r   r   r   r     rc   zIPythonHandler.allow_originc                 C   r`   )z*Regular expression version of allow_originallow_origin_patNrb   r)   r   r   r   r   "  rc   zIPythonHandler.allow_origin_patc                 C   r`   )z/Whether to set Access-Control-Allow-Credentialsallow_credentialsFrb   r)   r   r   r   r   '  rc   z IPythonHandler.allow_credentialsc                    s   t    | jr| d| j n.| jr&|  }|r%| j|r%| d| n| jr>d| j	di vr>| d| j
j	dd | jrI| dd dS dS )zAdd CORS headers, if definedAccess-Control-Allow-Originr#   Originr8   z Access-Control-Allow-CredentialstrueN)superr5   r   r/   r   
get_originmatchrW   r%   r&   rR   r#   r   r*   origin	__class__r   r   r5   ,  s&   
z"IPythonHandler.set_default_headersc                 C   s   t |}| dd|  dS )zpSet Content-Disposition: attachment header

        As a method to ensure handling of filename encoding
        zContent-Dispositionzattachment; filename*=utf-8''N)r   r/   )r*   filenameescaped_filenamer   r   r   set_attachment_headerB  s
   z$IPythonHandler.set_attachment_headerc                 C   s2   d| j jv r| j jd}|S | j jdd }|S )Nr   zSec-Websocket-Origin)rR   r#   r&   r   r   r   r   r   M  s
   zIPythonHandler.get_originr8   c                 C   s   | j dks	|  rdS | jjd}| jjd}|du s!|du r#dS | }t|j}||kr2dS | j r;| j |k}n| jrGt	| j
|}nd}|sV| jd| jj|| |S )zCheck Origin for cross-site API requests, including websockets

        Copied from WebSocket with changes:

        - allow unspecified host/origin (e.g. scripts)
        - allow token-authenticated requests
        *THostr   NFz?Blocking Cross Origin API request for %s.  Origin: %s, Host: %s)r   rU   rR   r#   r&   lowerr   netlocr   re   r   r    warningr:   )r*   origin_to_satisfy_tornador[   r   origin_hostallowr   r   r   check_originZ  s(   

zIPythonHandler.check_originc                 C   s   | j dks	|  rdS | jjd}| jjd}|s#| jd dS |s-| jd dS t|}|j}||kr:dS |j	 d|j }| j rL| j |k}n| j
rXt| j
|}nd}|sg| jd	| jj|| |S )
a^  Check Referer for cross-site requests.

        Disables requests to certain endpoints with
        external or missing Referer.

        If set, allow_origin settings are applied to the Referer
        to whitelist specific cross-origin sites.

        Used on GET for api endpoints and /files/
        to block cross-site inclusion (XSSI).
        r   Tr   RefererzBlocking request with no hostFz Blocking request with no refererz://z<Blocking Cross Origin request for %s.  Referer: %s, Host: %s)r   rU   rR   r#   r&   r    r   r   r   schemer   re   r   r:   )r*   r[   refererreferer_urlreferer_hostr   r   r   r   r   check_referer  s2   
zIPythonHandler.check_refererc              
      s   | j s
| jddrdS zt  W S  tjyK } z,| jjdv r?| 	 s>| jj
d}|r5d| d}nd}td	||n W Y d}~dS d}~ww )
z2Bypass xsrf cookie checks when token-authenticateddisable_check_xsrfFN>   GETHEADr   z#Blocking Cross Origin request from .z$Blocking request from unknown origin  )rW   r%   r&   r   check_xsrf_cookier   	HTTPErrorrR   rS   r   r#   )r*   r4   r   msgr   r   r   r     s"   z IPythonHandler.check_xsrf_cookiec                 C   s   | j ddr	dS td| jjd}|dr$|dr$|dd }t	|}|d	r6t
j|r6d}nzt|}W n tyP   || j d
dgv }Y nw |j}|s`| jd|| jj |S )zCheck the host header if remote access disallowed.

        Returns True if the request should continue, False otherwise.
        allow_remote_accessFTz^(.*?)(:\d+)?$   []r6   local_hostnames	localhostzBlocking request with non-local 'Host' %s (%s). If the notebook should be accessible at that name, set NotebookApp.allow_remote_access to disable the check.)r%   r&   rer   rR   r[   group
startswithendswithr   osr:   exists	ipaddress
ip_address
ValueErroris_loopbackr    r   )r*   r[   
check_hostr   addrr   r   r   r     s(   zIPythonHandler.check_hostc                       |   s	tdt  S Nr   )r   r   r   r   preparer)   r   r   r   r        

zIPythonHandler.preparec                 C   s   | j d |S )z1Return the jinja template object for a given name
jinja2_env)r%   get_template)r*   rC   r   r   r   r     s   zIPythonHandler.get_templatec                 K   s&   | | j | |}|jdi |S )Nr   )r-   template_namespacer   render)r*   rC   nstemplater   r   r   render_template  s   
zIPythonHandler.render_templatec                 C   s   t di d| jd| jd| jd| jd| jdd| jdt| j	d| j
d	t d
| jd| jd| jd| jd| j	d| jddtt| jjdd| jS )Nr(   rv   rx   r_   allow_password_changerg   token_available
static_urlsys_infory   rr   rn   xsrf_form_htmlrd   
xsrf_tokenutf8nbjs_translationszAccept-Languager8   r   )dictr(   rv   rx   r_   r%   r&   rg   re   rd   r   r   ry   rr   rn   r   r   decoder   r   r   rR   r#   rq   r)   r   r   r   r     sH   
	
z!IPythonHandler.template_namespacec              
   C   st   | j jsdS | j j d}zt|}W |S  ty9 } z| jd| | jj	ddd t
dd|d}~ww )	z,Return the body of the request as JSON data.Nzutf-8zBad JSON: %rzCouldn't parse JSONT)exc_infoi  zInvalid JSON in body of request)rR   bodystripr   r   loadsr0   r    r1   errorr   r   )r*   r   modelr4   r   r   r   get_json_body  s   zIPythonHandler.get_json_bodyc           
      K   s   | d}d}t |d}d}|r1|d }z|j|j }W n	 ty&   Y nw t|dd}|r1|}t||||d}| dd	 z| j| d
fi |}	W n t	y^   | jdi |}	Y nw | 
|	 dS )zrender custom error pagesr   r8   Unknown HTTP Errorz	(unknown)r   reason)status_codestatus_messagemessage	exceptionContent-Typez	text/htmlz.html
error.htmlN)r   )r&   r   log_messageargsr0   getattrr   r/   r   r   write)
r*   r   kwargsr   r   r   r   r   r   htmlr   r   r   write_error&  s6   
zIPythonHandler.write_errorr8   )'rh   ri   rj   rk   rl   rn   ro   r    rq   rr   rs   ru   r(   rv   rx   ry   r{   r~   r   r   r   r   r   r   r   r5   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   rm      sp    










	









,/%	
rm   c                       sp   e Zd ZdZ fddZdd Z fddZ fdd	Ze fd
dZ	dZ
dd Z fddZdd Z  ZS )
APIHandlerzBase class for API handlersc                    r   N  )r   r   r   r   r   r)   r   r   r   r   N  r   zAPIHandler.preparec                 K   s   |  dd t|d}d|i}|d}|r?|d }t|tr-|jp$||d< |j|d< nd|d< d	|d< d
tj	| |d< | j
|d  | t| d	S )z+APIHandler errors are JSON, not human pagesr   application/jsonr   r   r   r   r   zUnhandled errorNr8   	traceback)r/   r   r&   
isinstancer   r   r   r'   r   format_exceptionr    r   finishr   r   )r*   r   r   r   replyr   r4   r   r   r   r   S  s   

zAPIHandler.write_errorc                    s$   t | dr| jS t   | _}|S )zDRaise 403 on API handlers instead of redirecting to human login page_user_cache)rT   r   r   rO   r]   r   r   r   rO   g  s   
zAPIHandler.get_current_userc                    s   | j stdt  S r   )current_userr   r   r   get_login_urlr)   r   r   r   r   o  s   

zAPIHandler.get_login_urlc                    s   d t jdg}|S )Nr$   zdefault-src 'none')r'   r   r+   )r*   cspr   r   r   r+   w  s
   z"APIHandler.content_security_policyTc                 C   s>   | j rt| ddr| dddu rt | jd< dS dS dS dS )z$Update last_activity of API requestsr   Nno_track_activityapi_last_activity)_track_activityr   get_argumentr   r%   r)   r   r   r   update_api_activity  s   
zAPIHandler.update_api_activityc                    s&   |    | dd t j|i |S )Nr   r   )r   r/   r   r   r*   r   r   r   r   r   r     s   zAPIHandler.finishc                 O   s   d| j di v r| d| j d d  n| dd | dd | jjddd}|rWtd	d
 |D rY| jr[| jsI| j	sId| j di v r]| d| jjdd d S d S d S d S d S )NzAccess-Control-Allow-Headersr#   z0accept, content-type, authorization, x-xsrftokenzAccess-Control-Allow-Methodsz&GET, PUT, POST, PATCH, DELETE, OPTIONSzAccess-Control-Request-Headersr8   ,c                 s   s     | ]}|   d kV  qdS )authorizationN)r   r   ).0hr   r   r   	<genexpr>  s
    
z%APIHandler.options.<locals>.<genexpr>r   r   )
r%   r&   r/   rR   r#   splitanyrg   r   r   )r*   r   r   requested_headersr   r   r   options  s0   		

zAPIHandler.options)rh   ri   rj   rk   r   r   rO   r   rl   r+   r   r   r   r  r   r   r   r   r   r   K  s    
r   c                   @      e Zd ZdZdd ZdS )Template404zRender our 404 templatec                 C   s
   t dr   )r   r   r)   r   r   r   r     s   
zTemplate404.prepareN)rh   ri   rj   rk   r   r   r   r   r   r    s    r  c                       sp   e Zd ZdZe fddZej fddZejdd Z	 fdd	Z
 fd
dZdd Z fddZ  ZS )AuthenticatedFileHandlerz5static files should only be accessible when logged inc                    s   t  jd S )Nz; sandbox allow-scripts)r   r+   r)   r   r   r   r+     s   z0AuthenticatedFileHandler.content_security_policyc                    s   |    t |S r   )r   r   headr*   r:   r   r   r   r	    s   zAuthenticatedFileHandler.headc                 C   sP   |    tj|d dks| ddr!|ddd }| | tj	| |S )Nr   .ipynbdownloadFr6   r   )
r   r   r:   splitextr   rsplitr   r   StaticFileHandlerr&   )r*   r:   rC   r   r   r   r&     s
    
zAuthenticatedFileHandler.getc                    s\   | j d}d|v r|dd\}}n|}|drdS t|d }|dkr)dS t  S )Nr6   r   r  zapplication/x-ipynb+jsonr   z
text/plainztext/plain; charset=UTF-8)absolute_pathr   r  r   	mimetypes
guess_typer   get_content_type)r*   r:   _rC   cur_mimer   r   r   r    s   

z)AuthenticatedFileHandler.get_content_typec                    s*   t    d| jjvr| dd d S d S )NvCache-Controlno-cache)r   set_headersrR   	argumentsrA   r)   r   r   r   r    s   
z$AuthenticatedFileHandler.set_headersc                 C      d S r   r   r)   r   r   r   compute_etag     z%AuthenticatedFileHandler.compute_etagc                    sF   t  ||}tj|}t||r!| jjs!| j	d t
d|S )zValidate and return the absolute path.

        Requires tornado 3.1

        Adding to tornado's own handling, forbids the serving of hidden files.
        z_Refusing to serve hidden file, via 404 Error, use flag 'ContentsManager.allow_hidden' to enabler   )r   validate_absolute_pathr   r:   abspathr   r~   allow_hiddenr    infor   r   )r*   rootr  abs_pathabs_rootr   r   r   r    s   
z/AuthenticatedFileHandler.validate_absolute_path)rh   ri   rj   rk   rl   r+   r   authenticatedr	  r&   r  r  r  r  r   r   r   r   r   r    s    
	r  c                    s*   t jdtdd t  fdd}|S )a  Decorate methods with this to return GitHub style JSON errors.

    This should be used on any JSON API on any handler method that can raise HTTPErrors.

    This will grab the latest HTTPError exception using sys.exc_info
    and then:

    1. Set the HTTP status code based on the HTTPError
    2. Create and return a JSON body with a message field describing
       the error in a human readable form.
    zJ@json_errors is deprecated in notebook 5.2.0. Subclass APIHandler instead.   )
stacklevelc                    s&   t tj| | _ | g|R i |S r   )types
MethodTyper   r   r   rS   r   r   wrapper  s   zjson_errors.<locals>.wrapper)warningswarnDeprecationWarning	functoolswraps)rS   r+  r   r*  r   json_errors  s   r1  c                       sN   e Zd ZdZi Z fddZdddZdd Zed	d
 Z	 fddZ
  ZS )FileFindHandlerzBsubclass of StaticFileHandler for serving files from a search pathc                    sB   t    d jjvst fdd jD r dd d S d S )Nr  c                 3   s    | ]
} j j|V  qd S r   )rR   r:   r   )r   r:   r)   r   r   r    s    z.FileFindHandler.set_headers.<locals>.<genexpr>r  r  )r   r  rR   r  r  no_cache_pathsr/   r)   r   r)   r   r    s   
zFileFindHandler.set_headersNc                 C   s8   |pg | _ t|tr|g}tdd |D | _|| _d S )Nc                 s   s*    | ]}t jt j|t j V  qd S r   )r   r:   r  
expandusersep)r   pr   r   r   r  (  s    
z-FileFindHandler.initialize.<locals>.<genexpr>)r3  r   r   tupler"  default_filename)r*   r:   r8  r3  r   r   r   
initialize"  s   



zFileFindHandler.initializec                 C   r  r   r   r)   r   r   r   r  -  r  zFileFindHandler.compute_etagc              	   C   s   | j F || jv r| j| W  d   S ztjt||}W n ty0   Y W d   dS w || j|< t d||f  |W  d   S 1 sLw   Y  dS )z5locate a file to serve on our static file search pathNr8   zPath %s served from %s)	_lock_static_pathsr   r:   r  r   OSErrorr    r1   )clsrootsr:   r  r   r   r   get_absolute_path0  s   

$z!FileFindHandler.get_absolute_pathc                    s@   |dkr	t d| jD ]}|tj |r nqt ||S )z:check if the file should be served (raises 404, 403, etc.)r8   r   )r   r   r"  r   r5  r   r   r  )r*   r"  r  r   r   r   r  B  s   

z&FileFindHandler.validate_absolute_path)NN)rh   ri   rj   rk   r;  r  r9  r  classmethodr?  r  r   r   r   r   r   r2    s    

r2  c                   @   s   e Zd Zdd ZdS )APIVersionHandlerc                 C   s   |  tdtji d S )Nversion)r   r   r   notebook__version__r)   r   r   r   r&   P  s   zAPIVersionHandler.getN)rh   ri   rj   r&   r   r   r   r   rA  N  s    rA  c                   @   s    e Zd ZdZdd Ze ZZdS )TrailingSlashHandlerzrSimple redirect handler that strips trailing slashes

    This should be the first, highest priority handler.
    c                 C   s>   | j jd^}}d|d }d|g|}| | d S )N?r6   r8   )rR   uri	partitionr   r'   redirect)r*   r:   restnew_urir   r   r   r&   [  s   zTrailingSlashHandler.getN)rh   ri   rj   rk   r&   postputr   r   r   r   rE  U  s    rE  c                   @   s&   e Zd ZdZedd ZdddZdS )	FilesRedirectHandlerz<Handler for redirecting relative URLs to the /files/ handlerc                 C   s   | j }||rt| jdt|}n6|}|d}|j|ds4d|v r4| jd| |	d d
|}|j|ds?tdt| jdt|}| jd| jj| | | dS )	zgmake redirect logic a reusable static method

        so it can be called from other handlers.
        treer6   rG   fileszDeprecated files/ URL: %sr   zRedirecting %s to %sN)r~   
dir_existsr   r(   r   r  file_existsr    r   remover'   r   r   r1   rR   r:   rI  )r*   r:   cmrt   	orig_pathpartsr   r   r   redirect_to_filesi  s   




z&FilesRedirectHandler.redirect_to_filesr8   c                 C   s   |  | |S r   )rW  r
  r   r   r   r&     s   zFilesRedirectHandler.getNr   )rh   ri   rj   rk   staticmethodrW  r&   r   r   r   r   rN  f  s
    
rN  c                   @   s"   e Zd ZdZdddZdd ZdS )	RedirectWithParamsz8Sam as web.RedirectHandler, but preserves URL parametersTc                 C   s   || _ || _d S r   )_url
_permanent)r*   rt   	permanentr   r   r   r9    s   
zRedirectWithParams.initializec                 C   s:   d| j v rdnd}|| j | jjg}| j|| jd d S )NrF  &)r\  )rZ  r'   rR   queryrI  r[  )r*   r5  rt   r   r   r   r&     s   zRedirectWithParams.getN)T)rh   ri   rj   rk   r9  r&   r   r   r   r   rY    s    
rY  c                   @   r  )PrometheusMetricsHandlerz<
    Return prometheus metrics for this notebook server
    c                 C   s>   | j d r| jstd| dtj | ttj	 d S )Nauthenticate_prometheusr   r   )
r%   r_   r   r   r/   prometheus_clientCONTENT_TYPE_LATESTr   generate_latestREGISTRYr)   r   r   r   r&     s   
zPrometheusMetricsHandler.getN)rh   ri   rj   rk   r&   r   r   r   r   r_    s    r_  z(?P<path>(?:(?:/[^/]+)+|/?))z.*/apiz/(robots\.txt|favicon\.ico)z/metrics)Grk   r=   r/  r   r   r  r   r   sysr   r(  r,  http.clientr   http.cookiesr   urllib.parser   jinja2r   tornador   r   r   r	   tornado.logr
   ra  notebook._sysinfor   traitlets.configr   ipython_genutils.pathr   ipython_genutils.py3compatr   rC  notebook._tzr   notebook.i18nr   notebook.utilsr   r   r   r   r   notebook.services.securityr   compilerY   r   r   r    RequestHandlerr!   rm   r   r  r  r  r1  r   r2  rA  rE  rN  rY  r_  
path_regexdefault_handlersr   r   r   r   <module>   sn    
    f?9$