3
ò\ð]J  ã               @   s\   d dl Z d dlZd dlmZ G dd„ dƒZdd„ Zdd„ ZG d	d
„ d
eƒZdeeedœZ	dS )é    N)Úget_static_filec               @   s:   e Zd ZdZddd„Zdd„ Zdd	„ Zd
d„ Zdd„ ZdS )ÚASGIAppa°  ASGI application middleware for Engine.IO.

    This middleware dispatches traffic to an Engine.IO application. It can
    also serve a list of static files to the client, or forward unrelated
    HTTP traffic to another ASGI application.

    :param engineio_server: The Engine.IO server. Must be an instance of the
                            ``engineio.AsyncServer`` class.
    :param static_files: A dictionary with static file mapping rules. See the
                         documentation for details on this argument.
    :param other_asgi_app: A separate ASGI app that receives all other traffic.
    :param engineio_path: The endpoint where the Engine.IO application should
                          be installed. The default value is appropriate for
                          most cases.

    Example usage::

        import engineio
        import uvicorn

        eio = engineio.AsyncServer()
        app = engineio.ASGIApp(eio, static_files={
            '/': {'content_type': 'text/html', 'filename': 'index.html'},
            '/index.html': {'content_type': 'text/html',
                            'filename': 'index.html'},
        })
        uvicorn.run(app, '127.0.0.1', 5000)
    Nú	engine.ioc             C   s&   || _ || _|jdƒ| _|pi | _d S )Nú/)Úengineio_serverÚother_asgi_appÚstripÚengineio_pathÚstatic_files)Úselfr   r   r
   r	   © r   úF/tmp/pip-build-mqc4i71p/python-engineio/engineio/async_drivers/asgi.pyÚ__init__$   s    zASGIApp.__init__c             Ã   sÐ   |d dkr:|d j dj| jƒƒr:| jj|||ƒI d H  n’|d dkr\| jr\t|d | jƒnd }|rz| j|||ƒI d H  nR| jd k	rš| j|||ƒI d H  n2|d dkrº| j	||ƒI d H  n| j
||ƒI d H  d S )NÚtypeÚhttpÚ	websocketÚpathz/{0}/Úlifespan)r   r   )Ú
startswithÚformatr	   r   Úhandle_requestr
   r   Úserve_static_filer   r   Ú	not_found)r   ÚscopeÚreceiveÚsendÚstatic_filer   r   r   Ú__call__+   s    &
zASGIApp.__call__c             Ã   sœ   |ƒ I d H }|d dkr˜t jj|d ƒr†t|d dƒ�}|jƒ }W d Q R X |ddd|d jd	ƒfgd
œƒI d H  |d|dœƒI d H  n| j||ƒI d H  d S )Nr   zhttp.requestÚfilenameÚrbzhttp.response.startéÈ   s   Content-TypeÚcontent_typezutf-8)r   ÚstatusÚheaderszhttp.response.body)r   Úbody)Úosr   ÚexistsÚopenÚreadÚencoder   )r   r   r   r   ÚeventÚfÚpayloadr   r   r   r   ;   s    zASGIApp.serve_static_filec             Ã   sN   |ƒ I d H }|d dkr,|ddiƒI d H  n|d dkrJ|ddiƒI d H  d S )Nr   zlifespan.startupzlifespan.startup.completezlifespan.shutdownzlifespan.shutdown.completer   )r   r   r   r*   r   r   r   r   K   s
    zASGIApp.lifespanc             Ã   s0   |ddd
gdœƒI dH  |ddd	œƒI dH  dS )z+Return a 404 Not Found error to the client.zhttp.response.starti”  ó   Content-Typeó
   text/plain)r   r"   r#   Nzhttp.response.bodys	   Not Found)r   r$   )r-   r.   r   )r   r   r   r   r   r   r   R   s
    zASGIApp.not_found)NNr   )	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r   r   r      s    
r   c             Ã   sÄ  G dd„ dt ƒ}|ƒ I d H }d}|d dkrz||jdƒp:d7 }x^|jdƒrv|ƒ I d H }|d dkr@||jdƒppd7 }q@W n$|d dkrš|dd	iƒI d H  ni S | d
 jdƒ}d| krÌ| d rÌ|d| d  7 }||ƒtjd&ddddd| jddƒ| d
 | jddƒjdƒ|jdƒdddddd||dœ}xŽ| d D ]‚\}}	|jƒ jdƒ}|	jdƒ}	|dk�rb|	|d< �q*n|dk�rx|	|d< �q*d|jd d!ƒ }
|
|k�r¢d"||
 |	f }	|	||
< �q*W |jd#d$ƒ|d%< |S )'Nc               @   s   e Zd Zdd„ Zddd„ZdS )z+translate_request.<locals>.AwaitablePayloadc             S   s   |pd| _ d S )Nó    )r,   )r   r,   r   r   r   r   ]   s    z4translate_request.<locals>.AwaitablePayload.__init__Nc             Ó   s8   |d kr| j }d| _ n| j d |… }| j |d … | _ |S )Nr3   )r,   )r   ÚlengthÚrr   r   r   r(   `   s    z0translate_request.<locals>.AwaitablePayload.read)N)r/   r0   r1   r   r(   r   r   r   r   ÚAwaitablePayload\   s   r6   r3   r   zhttp.requestr$   Z	more_bodyzwebsocket.connectzwebsocket.acceptr   zutf-8Zquery_stringó   ?é   r   TFZasgiÚmethodÚGETÚ zHTTP/1.1z	127.0.0.1Ú0)z
wsgi.inputzwsgi.errorszwsgi.versionz
wsgi.asynczwsgi.multithreadzwsgi.multiprocesszwsgi.run_onceZSERVER_SOFTWAREÚREQUEST_METHODZ	PATH_INFOÚQUERY_STRINGZRAW_URIZSCRIPT_NAMEZSERVER_PROTOCOLZREMOTE_ADDRZREMOTE_PORTZSERVER_NAMEZSERVER_PORTzasgi.receivez	asgi.sendr#   zCONTENT-TYPEÚCONTENT_TYPEzCONTENT-LENGTHÚCONTENT_LENGTHzHTTP_%sú-Ú_z%s,%sZHTTP_X_FORWARDED_PROTOr   zwsgi.url_scheme)r8   r   )ÚobjectÚgetr)   ÚsysÚstderrÚdecodeÚupperÚreplace)r   r   r   r6   r*   r,   Zraw_uriÚenvironZhdr_nameZ	hdr_valueÚkeyr   r   r   Útranslate_request[   sd    




rL   c             Ã   sR   dd„ |D ƒ}|d dt | jdƒd ƒ|dœƒI d H  |d d|d	œƒI d H  d S )
Nc             S   s(   g | ] }|d  j dƒ|d j dƒf‘qS )r   zutf-8r8   )r)   )Ú.0Úhr   r   r   ú
<listcomp>¥   s    z!make_response.<locals>.<listcomp>z	asgi.sendzhttp.response.startú r   )r   r"   r#   zhttp.response.body)r   r$   )ÚintÚsplit)r"   r#   r,   rJ   r   r   r   Úmake_response¤   s    rS   c               @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú	WebSocketz�
    This wrapper class provides an asgi WebSocket interface that is
    somewhat compatible with eventlet's implementation.
    c             C   s   || _ d | _d | _d S )N)ÚhandlerÚasgi_receiveÚ	asgi_send)r   rU   r   r   r   r   ²   s    zWebSocket.__init__c             Ã   s(   |d | _ |d | _| j| ƒI d H  d S )Nzasgi.receivez	asgi.send)rV   rW   rU   )r   rJ   r   r   r   r   ·   s    

zWebSocket.__call__c             Ã   s   | j ddiƒI d H  d S )Nr   zwebsocket.close)rW   )r   r   r   r   Úclose¼   s    zWebSocket.closec             Ã   s8   d }d }t |tƒr|}n|}| jd||dœƒI d H  d S )Nzwebsocket.send)r   ÚbytesÚtext)Ú
isinstancerY   rW   )r   ÚmessageZ	msg_bytesZmsg_textr   r   r   r   ¿   s    
zWebSocket.sendc             Ã   s4   | j ƒ I d H }|d dkr tƒ ‚|jdƒp2|jdƒS )Nr   zwebsocket.receiverY   rZ   )rV   ÚIOErrorrD   )r   r*   r   r   r   ÚwaitÊ   s    zWebSocket.waitN)	r/   r0   r1   r2   r   r   rX   r   r^   r   r   r   r   rT   ­   s   rT   T)ZasynciorL   rS   r   )
r%   rE   Zengineio.static_filesr   r   rL   rS   rC   rT   Z_asyncr   r   r   r   Ú<module>   s   TI	%