U
    5øiª,  ã                   @   sÐ   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mZ d dlmZ d dlmZmZmZmZmZmZmZ d dlmZ d d	lmZ e  d
¡ZG dd„ deƒZG dd„ dejƒZ dS )é    N)ÚThreadSensitiveContextÚsync_to_async)Úsettings)Úsignals)ÚRequestAbortedÚRequestDataTooBig)Úbase)ÚFileResponseÚHttpRequestÚHttpResponseÚHttpResponseBadRequestÚHttpResponseServerErrorÚ	QueryDictÚparse_cookie)Úset_script_prefix)Úcached_propertyzdjango.requestc                       sn   e Zd ZdZdZdd„ Zedd„ ƒZ‡ fdd„Zd	d
„ Z	dd„ Z
dd„ Zee	e
ƒZeeƒZedd„ ƒZ‡  ZS )ÚASGIRequestzv
    Custom request subclass that decodes from an ASGI-standard request dict
    and wraps request body handling.
    é<   c                 C   s  || _ d| _d| _d | _| j  dd¡| _| jrX|d  | j¡rX|d t| jƒd … | _n
|d | _| jrŒd| j 	d¡| j 
ddd¡f | _n
|d | _| j d  ¡ | _| j  d	d¡}t|tƒrÆ| ¡ }| j|| j| jd
d
dœ| _| j  d¡�r&| j d d | jd< | jd | jd< | j d d | jd< | j  d¡�rb| j d d | jd< t| j d d ƒ| jd< nd| jd< d| jd< | j  dg ¡D ]z\}}| d¡}|dk�r¦d}n$|dk�r¶d}nd| ¡  
dd¡ }| d¡}|| jk�rò| j| d | }|| j|< �q„|  | j¡ || _d | _d S ) NFÚ	root_pathÚ Úpathz%s/%sú/é   ÚmethodÚquery_stringT)ÚREQUEST_METHODÚQUERY_STRINGZSCRIPT_NAMEZ	PATH_INFOzwsgi.multithreadzwsgi.multiprocessÚclientr   ZREMOTE_ADDRZREMOTE_HOSTZREMOTE_PORTÚserverZSERVER_NAMEZSERVER_PORTÚunknownÚ0ÚheadersÚlatin1zcontent-lengthÚCONTENT_LENGTHzcontent-typeÚCONTENT_TYPEzHTTP_%sú-Ú_ú,)ÚscopeZ_post_parse_errorZ_read_startedZresolver_matchÚgetÚscript_nameÚ
startswithÚlenZ	path_infoÚrstripÚreplacer   Úupperr   Ú
isinstanceÚbytesÚdecodeÚMETAÚstrZ_set_content_type_paramsÚ_stream)Úselfr(   Ú	body_filer   ÚnameÚvalueZcorrected_name© r:   ú=/tmp/pip-unpacked-wheel-gcyiijx6/django/core/handlers/asgi.pyÚ__init__   s`    

þ


ù	





zASGIRequest.__init__c                 C   s   t | jd ƒS )Nr   )r   r3   ©r6   r:   r:   r;   ÚGETb   s    zASGIRequest.GETc                    s   | j  d¡ptƒ  ¡ S )NÚscheme)r(   r)   ÚsuperÚ_get_schemer=   ©Ú	__class__r:   r;   rA   f   s    zASGIRequest._get_schemec                 C   s   t | dƒs|  ¡  | jS )NÚ_post)ÚhasattrÚ_load_post_and_filesrD   r=   r:   r:   r;   Ú	_get_posti   s    
zASGIRequest._get_postc                 C   s
   || _ d S )N)rD   )r6   Úpostr:   r:   r;   Ú	_set_postn   s    zASGIRequest._set_postc                 C   s   t | dƒs|  ¡  | jS )NÚ_files)rE   rF   rJ   r=   r:   r:   r;   Ú
_get_filesq   s    
zASGIRequest._get_filesc                 C   s   t | j dd¡ƒS )NZHTTP_COOKIEr   )r   r3   r)   r=   r:   r:   r;   ÚCOOKIESy   s    zASGIRequest.COOKIES)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Zbody_receive_timeoutr<   r   r>   rA   rG   rI   rK   ÚpropertyÚPOSTZFILESrL   Ú__classcell__r:   r:   rB   r;   r      s   C

r   c                       sp   e Zd ZdZeZdZ‡ fdd„Zdd„ Zdd„ Z	d	d
„ Z
dd„ Z‡ fdd„Zdd„ Zedd„ ƒZdd„ Z‡  ZS )ÚASGIHandlerzHandler for ASGI requests.i   c                    s   t ƒ  ¡  | jdd� d S )NT)Zis_async)r@   r<   Zload_middlewarer=   rB   r:   r;   r<   „   s    
zASGIHandler.__init__c              
   Ã   sT   |d dkrt d|d  ƒ‚tƒ 4 I dH š |  |||¡I dH  W 5 Q I dH R X dS )zV
        Async entrypoint - parses the request and hands off to get_response.
        ÚtypeÚhttpz5Django can only handle ASGI/HTTP connections, not %s.N)Ú
ValueErrorr   Úhandle)r6   r(   ÚreceiveÚsendr:   r:   r;   Ú__call__ˆ   s    ÿÿzASGIHandler.__call__c                 Ã   sÈ   z|   |¡I dH }W n tk
r*   Y dS X t|  |¡ƒ ttjjdd�| j|d�I dH  |  	||¡\}}|dkrˆ|  
||¡I dH  dS |  |¡I dH }| j|_t|tƒr²| j|_|  
||¡I dH  dS )zK
        Handles the ASGI request. Called via the __call__ method.
        NT©Zthread_sensitive)Zsenderr(   )Ú	read_bodyr   r   Úget_script_prefixr   r   Zrequest_startedrZ   rC   Úcreate_requestÚsend_responseZget_response_asyncZ_handler_classr0   r	   Ú
chunk_sizeÚ
block_size)r6   r(   rY   rZ   r7   ÚrequestZerror_responseÚresponser:   r:   r;   rX   —   s     
zASGIHandler.handlec                 Ã   sb   t jtjdd�}|ƒ I dH }|d dkr.tƒ ‚d|krD| |d ¡ | dd¡sqTq| d	¡ |S )
z+Reads an HTTP body from an ASGI connection.zw+b)Úmax_sizeÚmodeNrU   zhttp.disconnectÚbodyÚ	more_bodyFr   )ÚtempfileÚSpooledTemporaryFiler   ZFILE_UPLOAD_MAX_MEMORY_SIZEr   Úwriter)   Úseek)r6   rY   r7   Úmessager:   r:   r;   r]   ²   s    
zASGIHandler.read_bodyc                 C   sp   z|   ||¡dfW S  tk
rH   tjdt ¡ ddid� dtƒ f Y S  tk
rj   dtddd�f Y S X dS )	z‰
        Create the Request object and returns either (request, None) or
        (None, response) if there is an error response.
        Nz Bad Request (UnicodeDecodeError)Ústatus_codei�  )Úexc_infoÚextraz413 Payload too largei�  )Ústatus)	Úrequest_classÚUnicodeDecodeErrorÚloggerÚwarningÚsysro   r   r   r   )r6   r(   r7   r:   r:   r;   r_   Ä   s    ýzASGIHandler.create_requestc                    sF   zt ƒ  |||¡W S  tk
r@   ttjr2t ¡ nddd� Y S X dS )z#Last-chance handler for exceptions.zInternal Server Errorz
text/plain)Úcontent_typeN)r@   Úhandle_uncaught_exceptionÚ	Exceptionr   r   ÚDEBUGÚ	tracebackÚ
format_exc)r6   rc   Úresolverro   rB   r:   r;   rx   Õ   s    þz%ASGIHandler.handle_uncaught_exceptionc                 Ã   s2  g }|  ¡ D ]F\}}t|tƒr(| d¡}t|tƒr<| d¡}| t|ƒt|ƒf¡ q|j ¡ D ]$}| d|jdd� d¡ 	¡ f¡ q^|d|j
|dœƒI dH  |jrê|D ].}|  |¡D ]\}}	|d	|d
dœƒI dH  q´q¦|dd	iƒI dH  n.|  |j¡D ] \}}
|d	||
 dœƒI dH  qöt|jd
d�ƒ I dH  dS )z)Encode and send a response out over ASGI.Úasciir"   s
   Set-Cookier   )Úheaderzhttp.response.start)rU   rq   r!   Nzhttp.response.bodyT)rU   rg   rh   rU   r\   )Úitemsr0   r4   ÚencodeÚappendr1   ÚcookiesÚvaluesÚoutputÚstriprn   Z	streamingÚchunk_bytesÚcontentr   Úclose)r6   rd   rZ   Úresponse_headersr   r9   ÚcÚpartÚchunkr&   Úlastr:   r:   r;   r`   á   s@    



ÿýûýzASGIHandler.send_responsec                 c   sX   d}|s|dfV  dS |t |ƒk rT|||| j … || j t |ƒkfV  || j7 }qdS )z
        Chunks some data up so it can be sent in reasonable size messages.
        Yields (chunk, last_chunk) tuples.
        r   TN)r,   ra   )ÚclsÚdataÚpositionr:   r:   r;   r‡     s    
þzASGIHandler.chunk_bytesc                 C   s   t jrt jS | dd¡pdS )zU
        Return the script prefix to use from either the scope or a setting.
        r   r   )r   ZFORCE_SCRIPT_NAMEr)   )r6   r(   r:   r:   r;   r^   !  s    zASGIHandler.get_script_prefix)rM   rN   rO   rP   r   rr   ra   r<   r[   rX   r]   r_   rx   r`   Úclassmethodr‡   r^   rS   r:   r:   rB   r;   rT   ~   s   /
rT   )!Úloggingrv   ri   r{   Zasgiref.syncr   r   Zdjango.confr   Zdjango.corer   Zdjango.core.exceptionsr   r   Zdjango.core.handlersr   Zdjango.httpr	   r
   r   r   r   r   r   Zdjango.urlsr   Zdjango.utils.functionalr   Ú	getLoggerrt   r   ÚBaseHandlerrT   r:   r:   r:   r;   Ú<module>   s   $
h