B
    HVvg¯  ã               @   sH   d dl mZ d dlmZ d dlmZmZ G dd„ dƒZG dd„ dƒZdS )	é    )ÚBytesIO)ÚSpooledTemporaryFile)ÚAsyncToSyncÚsync_to_asyncc               @   s    e Zd ZdZdd„ Zdd„ ZdS )Ú
WsgiToAsgizG
    Wraps a WSGI application to make it into an ASGI application.
    c             C   s
   || _ d S )N)Úwsgi_application)Úselfr   © r	   ú1/tmp/pip-install-o3oxmrkh/asgiref/asgiref/wsgi.pyÚ__init__   s    zWsgiToAsgi.__init__c             Ã   s   t | jƒ|||ƒI dH  dS )z¸
        ASGI application instantiation point.
        We return a new WsgiToAsgiInstance here with the WSGI app
        and the scope, ready to respond when it is __call__ed.
        N)ÚWsgiToAsgiInstancer   )r   ÚscopeÚreceiveÚsendr	   r	   r
   Ú__call__   s    zWsgiToAsgi.__call__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r	   r	   r	   r
   r      s   r   c               @   s>   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	d
„Zedd„ ƒZ	dS )r   z;
    Per-socket instance of a wrapped WSGI application
    c             C   s   || _ d| _d | _d S )NF)r   Úresponse_startedÚresponse_content_length)r   r   r	   r	   r
   r      s    zWsgiToAsgiInstance.__init__c          	   Ã   sœ   |d dkrt dƒ‚|| _tdd��n}xB|ƒ I d H }|d dkrHt dƒ‚| | dd	¡¡ | d
¡s(P q(W | d¡ t|ƒ| _|  |¡I d H  W d Q R X d S )NÚtypeÚhttpz&WSGI wrapper received a non-HTTP scopei   )Úmax_sizezhttp.requestz0WSGI wrapper received a non-HTTP-request messageÚbodyó    Ú	more_bodyr   )	Ú
ValueErrorr   r   ÚwriteÚgetÚseekr   Ú	sync_sendÚrun_wsgi_app)r   r   r   r   r   Úmessager	   r	   r
   r   "   s    


zWsgiToAsgiInstance.__call__c             C   s>  |d |  dd¡ d¡ d¡|d  d¡ d¡|d  d¡d	|d
  d|  dd¡|tƒ ddddœ}d|kr�|d d |d< t|d d ƒ|d< nd|d< d|d< d|kr¸|d d |d< x€| j  dg ¡D ]n\}}| d¡}|dkrèd}n"|dkröd}nd| ¡  d d!¡ }| d¡}||k�r.|| d" | }|||< qÈW |S )#zM
        Builds a scope and request body into a WSGI environ object.
        ÚmethodÚ	root_pathÚ Úutf8Úlatin1ÚpathZquery_stringÚasciizHTTP/%sÚhttp_version)é   r   Úschemer   TF)ÚREQUEST_METHODZSCRIPT_NAMEZ	PATH_INFOÚQUERY_STRINGZSERVER_PROTOCOLzwsgi.versionzwsgi.url_schemez
wsgi.inputzwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_onceÚserverr   ZSERVER_NAMEr,   ZSERVER_PORTÚ	localhostÚ80ÚclientZREMOTE_ADDRÚheaderszcontent-lengthÚCONTENT_LENGTHzcontent-typeÚCONTENT_TYPEzHTTP_%sú-Ú_ú,)r   ÚencodeÚdecoder   Ústrr   ÚupperÚreplace)r   r   r   ÚenvironÚnameÚvalueZcorrected_namer	   r	   r
   Úbuild_environ5   s>    




z WsgiToAsgiInstance.build_environNc       	      C   s˜   | j r|d  |d ¡‚t| dƒr2|dkr2tdƒ‚| dd¡\}}t|ƒ}dd„ |D ƒ}d| _x&|D ]\}}| ¡ d	krdt|ƒ| _qdW d
||dœ| _dS )z/
        WSGI start_response callable.
        r,   é   Úresponse_startNz=You cannot call start_response a second time without exc_infoú c             S   s(   g | ] \}}|  ¡  d ¡| d ¡f‘qS )r*   )Úlowerr:   )Ú.0r@   rA   r	   r	   r
   ú
<listcomp>s   s   z5WsgiToAsgiInstance.start_response.<locals>.<listcomp>zcontent-lengthzhttp.response.start)r   Ústatusr4   )	r   Úwith_tracebackÚhasattrr   ÚsplitÚintr   rF   rD   )	r   rI   Úresponse_headersÚexc_infoÚstatus_coder8   r4   r@   rA   r	   r	   r
   Ústart_responseb   s     z!WsgiToAsgiInstance.start_responsec             C   sÂ   |   | j|¡}d}x„|  || j¡D ]r}| js>d| _|  | j¡ | jdk	rj| j| }t|ƒ|krj|d|… }|  d|ddœ¡ |t|ƒ7 }|| jkr"P q"W | js°d| _|  | j¡ |  ddi¡ dS )zŸ
        Called in a subthread to run the WSGI app. We encapsulate like
        this so that the start_response callable is called in the same thread.
        r   TNzhttp.response.body)r   r   r   r   )	rB   r   r   rQ   r   r!   rD   r   Úlen)r   r   r?   Z
bytes_sentÚoutputZbytes_allowedr	   r	   r
   r"   ‚   s&    


zWsgiToAsgiInstance.run_wsgi_app)N)
r   r   r   r   r   r   rB   rQ   r   r"   r	   r	   r	   r
   r      s   -
 r   N)	Úior   Útempfiler   Zasgiref.syncr   r   r   r   r	   r	   r	   r
   Ú<module>   s   