B
    ind"                 @   s   d dl Zd dlZd dlZd dlZd dlmZ d dl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mZmZ ejedf ZG dd	 d	eZG d
d dZdS )    N)	parsedate)URLHeaders)HTTPException)FileResponseRedirectResponseResponse)ReceiveScopeSendzos.PathLike[str]c                   s&   e Zd ZdZed fddZ  ZS )NotModifiedResponse)zcache-controlzcontent-locationdateetagexpiresvary)headersc                s&   t  jd fdd| D d d S )Ni0  c                s    i | ]\}}| j kr||qS  )NOT_MODIFIED_HEADERS).0namevalue)selfr   9/tmp/pip-unpacked-wheel-_bom8ime/starlette/staticfiles.py
<dictcomp>   s   z0NotModifiedResponse.__init__.<locals>.<dictcomp>)status_coder   )super__init__items)r   r   )	__class__)r   r   r      s    
zNotModifiedResponse.__init__)__name__
__module____qualname__r   r   r   __classcell__r   r   )r   r   r      s   r   c            	   @   s*  e Zd Zddddddeje ejejejeej	eef f   e
e
e
ddddZd!eje ejejejeej	eef f   eje dd	d
ZeeeddddZeedddZeeedddZeej	eejej f dddZd"eejeeedddZddddZeee
ddd ZdS )#StaticFilesNFT)	directorypackageshtml	check_dirfollow_symlink)r$   r%   r&   r'   r(   returnc            C   sX   || _ || _| ||| _|| _d| _|| _|rT|d k	rTtj	|sTt
d| dd S )NFzDirectory 'z' does not exist)r$   r%   get_directoriesall_directoriesr&   config_checkedr(   ospathisdirRuntimeError)r   r$   r%   r&   r'   r(   r   r   r   r   '   s    zStaticFiles.__init__)r$   r%   r)   c             C   s   g }|dk	r| | x|pg D ]}t|tr8|\}}nd}tj|}|dk	s`td|d|jdk	sztd|dtj	
tj	|jd|}tj	|std|d|d| | q W |S )z
        Given `directory` and `packages` arguments, return a list of all the
        directories that should be used for serving static files from.
        NZstaticszPackage z could not be found.z..zDirectory 'z' in package )append
isinstancetuple	importlibutil	find_specAssertionErrororiginr-   r.   normpathjoinr/   )r   r$   r%   directoriespackageZstatics_dirspecZpackage_directoryr   r   r   r*   ;   s"    


zStaticFiles.get_directories)scopereceivesendr)   c                s\   |d dkst | js*|  I dH  d| _| |}| ||I dH }||||I dH  dS )z'
        The ASGI entry point.
        typehttpNT)r7   r,   check_configget_pathget_response)r   r>   r?   r@   r.   responser   r   r   __call__\   s    
zStaticFiles.__call__)r>   r)   c             C   s   t jt jj|d d S )z
        Given the ASGI scope, return the `path` string to serve up,
        with OS specific path separators, and any '..', '.' components removed.
        r.   /)r-   r.   r9   r:   split)r   r>   r   r   r   rD   j   s    zStaticFiles.get_path)r.   r>   r)   c                s~  |d dkrt ddytj| j|I dH \}}W n2 tk
rR   t ddY n tk
rf    Y nX |rt|j	r| 
|||S |r&t|j	r&| jr&tj|d}tj| j|I dH \}}|dk	r&t|j	r&|d d	st|d
}|j|jd	 d}t|dS | 
|||S | jrptj| jdI dH \}}|rpt|j	rpt|||d ddS t dddS )z`
        Returns an HTTP response, given the incoming path, method and request headers.
        method)GETHEADi  )r   Ni  z
index.htmlr.   rH   )r>   )r.   )urlz404.htmli  )stat_resultrJ   r   )r   anyio	to_threadrun_synclookup_pathPermissionErrorOSErrorstatS_ISREGst_modefile_responseS_ISDIRr&   r-   r.   r:   endswithr   replacer   r   )r   r.   r>   	full_pathrN   Z
index_pathrM   r   r   r   rE   q   s>    


zStaticFiles.get_response)r.   r)   c          
   C   s   x| j D ]~}tj||}| jr.tj|}ntj|}tj|}tj||g|kr\qy|t|fS  t	t
fk
r   wY qX qW dS )N) N)r+   r-   r.   r:   r(   abspathrealpath
commonpathrU   FileNotFoundErrorNotADirectoryError)r   r.   r$   Zjoined_pathr\   r   r   r   rR      s    zStaticFiles.lookup_path   )r\   rN   r>   r   r)   c             C   s>   |d }t |d}t||||d}| |j|r:t|jS |S )NrJ   )r>   )r   rN   rJ   )r   r   is_not_modifiedr   r   )r   r\   rN   r>   r   rJ   request_headersrF   r   r   r   rX      s    

zStaticFiles.file_response)r)   c                s   | j dkrdS ytjtj| j I dH }W n& tk
rP   td| j  dY nX t|j	s|t
|j	s|td| j  ddS )z
        Perform a one-off configuration check that StaticFiles is actually
        pointed at a directory, so that we can raise loud errors rather than
        just returning 404 responses.
        NzStaticFiles directory 'z' does not exist.zStaticFiles path 'z' is not a directory.)r$   rO   rP   rQ   r-   rU   ra   r0   rY   rW   S_ISLNK)r   rN   r   r   r   rC      s    
zStaticFiles.check_config)response_headersre   r)   c             C   s   y |d }|d }||krdS W n t k
r4   Y nX y8t|d }t|d }|dk	rl|dk	rl||krldS W n t k
r   Y nX dS )z
        Given the request and response headers, return `True` if an HTTP
        "Not Modified" response could be returned instead.
        zif-none-matchr   Tzif-modified-sincezlast-modifiedNF)KeyErrorr   )r   rg   re   Zif_none_matchr   Zif_modified_sinceZlast_modifiedr   r   r   rd      s"    zStaticFiles.is_not_modified)NN)rc   )r   r    r!   typingOptionalPathLikeListUnionstrTupleboolr   r*   r
   r	   r   rG   rD   r   rE   r-   rN   rR   intrX   rC   r   rd   r   r   r   r   r#   &   s&   6 ,2 r#   )Zimportlib.utilr4   r-   rU   ri   email.utilsr   rO   Zstarlette.datastructuresr   r   Zstarlette.exceptionsr   Zstarlette.responsesr   r   r   Zstarlette.typesr	   r
   r   rm   rn   rk   r   r#   r   r   r   r   <module>   s   