U
    mf.                     @   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rd| 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rd}n$|dkrd}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-siwebuq3/django/core/handlers/asgi.py__init__%   s`    




	





zASGIRequest.__init__c                 C   s   t | jd S )Nr   )r   r3   r6   r:   r:   r;   GETh   s    zASGIRequest.GETc                    s   | j dpt  S )Nscheme)r(   r)   super_get_schemer=   	__class__r:   r;   rA   l   s    zASGIRequest._get_schemec                 C   s   t | ds|   | jS )N_post)hasattr_load_post_and_filesrD   r=   r:   r:   r;   	_get_posto   s    
zASGIRequest._get_postc                 C   s
   || _ d S )N)rD   )r6   postr:   r:   r;   	_set_postt   s    zASGIRequest._set_postc                 C   s   t | ds|   | jS )N_files)rE   rF   rJ   r=   r:   r:   r;   
_get_filesw   s    
zASGIRequest._get_filesc                 C   s   t | jddS )NZHTTP_COOKIEr   )r   r3   r)   r=   r:   r:   r;   COOKIES   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 z|t| | ttjjdd| j	|dI dH  | 
||\}}|dkr| ||I dH  W  dS | |I dH }| j	|_W 5 |  X 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   closer   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                    sj   t jtjdd}| I dH }|d dkr6|  t d|krL||d  |ddsq\q|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^   r   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sysrp   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   rd   resolverrp   rB   r:   r;   ry      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  qq|dd	iI dH  n.| |jD ] \}}
|d	||
 dI dH  qt|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   rr   r!   Nzhttp.response.bodyT)rU   rh   ri   rU   r\   )itemsr0   r4   encodeappendr1   cookiesvaluesoutputstripro   Z	streamingchunk_bytescontentr   r^   )r6   re   rZ   response_headersr   r9   cpartchunkr&   lastr:   r:   r;   ra      sF    





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,   rb   )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_   5  s    zASGIHandler.get_script_prefix)rM   rN   rO   rP   r   rs   rb   r<   r[   rX   r]   r`   ry   ra   classmethodr   r_   rS   r:   r:   rB   r;   rT      s    5
rT   )!loggingrw   rj   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   	getLoggerru   r   BaseHandlerrT   r:   r:   r:   r;   <module>   s   $	
i