U
    tb                     @  s   d dl mZ d dl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 d dlmZ d d	lmZ d
ZdZdZdZdZdZG dd deZG dd deZdS )    )annotationsN)Any)ParseResulturlparse)HttpRequestHttpResponse)patch_vary_headers)MiddlewareMixin)conf)check_request_enabledzAccess-Control-Allow-OriginzAccess-Control-Expose-Headersz Access-Control-Allow-CredentialszAccess-Control-Allow-HeaderszAccess-Control-Allow-MethodszAccess-Control-Max-Agec                   @  sB   e Zd ZdddddZdddddZdddddd	d
dZdS )CorsPostCsrfMiddlewarer   Nonerequestreturnc                 C  s0   t jr,d|jkr,|jd }||jd< |jd= dS )zj
        Put the HTTP_REFERER back to its original value and delete the
        temporary storage
        ORIGINAL_HTTP_REFERERHTTP_REFERERN)r
   CORS_REPLACE_HTTPS_REFERERMETA)selfr   http_referer r   :/tmp/pip-unpacked-wheel-h03uz43q/corsheaders/middleware.py_https_referer_replace_reverse   s    

z5CorsPostCsrfMiddleware._https_referer_replace_reversec                 C  s   |  | d S Nr   r   r   r   r   r   process_request!   s    
z&CorsPostCsrfMiddleware.process_requestr   r   callbackcallback_argscallback_kwargsr   c                 C  s   |  | d S r   r   r   r   r   r    r!   r   r   r   process_view%   s    
z#CorsPostCsrfMiddleware.process_viewN)__name__
__module____qualname__r   r   r#   r   r   r   r   r      s   
r   c                   @  s   e Zd ZdddddZdddddZdd	d	d	dd
ddZddddddZddddddZdddddZdddddZ	dddddZ
ddddd Zd!S )"CorsMiddlewarer   r   r   c                 C  s   |j d}| r|rd|j krt|}tjs@| ||s@dS z<|j d }d|j d  }|j  |_ ||j d< ||j d< W n tk
r   Y nX dS )a  
        When https is enabled, django CSRF checking includes referer checking
        which breaks when using CORS. This function updates the HTTP_REFERER
        header to make sure it matches HTTP_HOST, provided that our cors logic
        succeeds
        HTTP_ORIGINr   Nr   zhttps://%s/Z	HTTP_HOST)	r   getZ	is_securer   r
   CORS_ALLOW_ALL_ORIGINSorigin_found_in_white_listscopyKeyError)r   r   originurlr   Z	http_hostr   r   r   _https_referer_replace1   s*    


z%CorsMiddleware._https_referer_replacezHttpResponse | Nonec                 C  sL   |  ||_|jrHtjr"| | |jdkrHd|jkrHt }d|d< |S dS )a  
        If CORS preflight header, then create an
        empty body response (200 OK) and return it

        Django won't bother calling any other request
        view/exception middleware along with the requested view;
        it will call any response middlewares
        OPTIONSZ"HTTP_ACCESS_CONTROL_REQUEST_METHOD0zContent-LengthN)
is_enabled_cors_enabledr
   r   r0   methodr   r   )r   r   responser   r   r   r   P   s    	
zCorsMiddleware.process_requestr   r   c                 C  s   |j rtjr| | dS )z9
        Do the referer replacement here as well
        N)r4   r
   r   r0   r"   r   r   r   r#   g   s    

zCorsMiddleware.process_viewr   )r   r6   r   c                 C  s  t |dd}|dkr| |}|s&|S t|dg |jd}|sF|S zt|}W n tk
rj   | Y S X tjrzd|t	< tj
s| ||s| |s|S tj
rtjsd|t< n||t< ttjrdtj|t< |jdkrdtj|t< dtj|t< tjrttj|t< |S )	z1
        Add the respective CORS headers
        r4   NZOriginr(   true*z, r1   )getattrr3   r   r   r)   r   
ValueErrorr
   ZCORS_ALLOW_CREDENTIALS ACCESS_CONTROL_ALLOW_CREDENTIALSr*   r+   check_signalACCESS_CONTROL_ALLOW_ORIGINlenZCORS_EXPOSE_HEADERSjoinACCESS_CONTROL_EXPOSE_HEADERSr5   ZCORS_ALLOW_HEADERSACCESS_CONTROL_ALLOW_HEADERSZCORS_ALLOW_METHODSACCESS_CONTROL_ALLOW_METHODSZCORS_PREFLIGHT_MAX_AGEstrACCESS_CONTROL_MAX_AGE)r   r   r6   enabledr.   r/   r   r   r   process_responseu   sF    




zCorsMiddleware.process_responserC   r   bool)r.   r/   r   c                 C  s&   |dkr|t jkp$| |p$| |S )Nnull)r
   CORS_ALLOWED_ORIGINS_url_in_whitelistregex_domain_match)r   r.   r/   r   r   r   r+      s
    z*CorsMiddleware.origin_found_in_white_lists)r.   r   c                   s   t  fddtjD S )Nc                 3  s   | ]}t | V  qd S r   )rematch).0Zdomain_patternr.   r   r   	<genexpr>   s   z4CorsMiddleware.regex_domain_match.<locals>.<genexpr>)anyr
   ZCORS_ALLOWED_ORIGIN_REGEXES)r   r.   r   rO   r   rK      s    z!CorsMiddleware.regex_domain_matchc                 C  s   t ttj|jp| |S r   )rG   rL   rM   r
   ZCORS_URLS_REGEXZ	path_infor<   r   r   r   r   r3      s
    zCorsMiddleware.is_enabledc                 C  s    t jd |d}tdd |D S )N)Zsenderr   c                 s  s   | ]\}}|V  qd S r   r   )rN   functionZreturn_valuer   r   r   rP      s     z.CorsMiddleware.check_signal.<locals>.<genexpr>)r   sendrQ   )r   r   Zsignal_responsesr   r   r   r<      s    zCorsMiddleware.check_signal)r/   r   c                   s&   dd t jD }t fdd|D S )Nc                 S  s   g | ]}t |qS r   )r   )rN   or   r   r   
<listcomp>   s     z4CorsMiddleware._url_in_whitelist.<locals>.<listcomp>c                 3  s&   | ]}|j  j ko|j jkV  qd S r   )schemenetloc)rN   r.   r/   r   r   rP      s   z3CorsMiddleware._url_in_whitelist.<locals>.<genexpr>)r
   rI   rQ   )r   r/   Zoriginsr   rX   r   rJ      s    z CorsMiddleware._url_in_whitelistN)r$   r%   r&   r0   r   r#   rF   r+   rK   r3   r<   rJ   r   r   r   r   r'   0   s   4r'   )
__future__r   rL   typingr   urllib.parser   r   Zdjango.httpr   r   Zdjango.utils.cacher   Zdjango.utils.deprecationr	   Zcorsheaders.confr
   Zcorsheaders.signalsr   r=   r@   r;   rA   rB   rD   r   r'   r   r   r   r   <module>   s    