U
    9ÜŸj(@  ã                   @   s®   d dl Z d dlZd dlZd dl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d	lmZmZ e  e¡ZG d
d„ dejƒZee	ƒG dd„ dejƒƒZdS )é    N)Úunquote)ÚinlineCallbacksÚmaybeDeferred)ÚIProtocolNegotiationFactory)ÚProtocolWrapper)Úhttp)Úimplementeré   )ÚHEADER_NAME_REÚparse_x_forwarded_forc                   @   s˜   e Zd ZdZd dd¡ dd¡ dd¡ dd¡Zd	d
„ Zedd„ ƒZdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!S )"Ú
WebRequestzÌ
    Request that either hands off information to channels, or offloads
    to a WebSocket class.

    Does some extra processing over the normal Twisted Web request to separate
    GET and POST out.
    a�  
        <html>
            <head>
                <title>%(title)s</title>
                <style>
                    body { font-family: sans-serif; margin: 0; padding: 0; }
                    h1 { padding: 0.6em 0 0.2em 20px; color: #896868; margin: 0; }
                    p { padding: 0 0 0.3em 20px; margin: 0; }
                    footer { padding: 1em 0 0.3em 20px; color: #999; font-size: 80%%; font-style: italic; }
                </style>
            </head>
            <body>
                <h1>%(title)s</h1>
                <p>%(body)s</p>
                <footer>Daphne</footer>
            </body>
        </html>
    Ú
Ú z    ú z   z  c                 O   sr   d | _ d | _z<tjj| f|ž|Ž | jjj| _d | _d| _	| j 
| ¡ W n$ tk
rl   t t ¡ ¡ ‚ Y nX d S )NF)Úclient_addrÚserver_addrr   ÚRequestÚ__init__ÚchannelÚfactoryÚserverÚapplication_queueÚ_response_startedZprotocol_connectedÚ	ExceptionÚloggerÚerrorÚ	tracebackÚ
format_exc)ÚselfÚargsÚkwargs© r!   ú8/tmp/pip-unpacked-wheel-tk6c4rm9/daphne/http_protocol.pyr   4   s    zWebRequest.__init__c                 c   s4  �zút   ¡ | _| j ¡ D ](\}}t |¡s|  ddd¡  W d S qd }| j d¡rb| j d¡d }t	| j
dƒr¦t	| j
dƒr¦t| j
jƒ| j
jg| _t| jjƒ| jjg| _|  ¡ r²dnd	| _| jjrìt| j| jj| jj| jj| j| jƒ\| _| _z| j d
¡ W n. tk
�r*   d| _|  ddd¡ Y W d S X d| _d| jk�rŒ| j dd¡d | _z| j d
¡ W n( tk
�rŠ   |  ddd¡ Y W d S X |�r¢| ¡ dk�r¢| jj | j  !¡ ¡}|�sÖ|  "d¡ t# $d¡ |  %¡  | j|_&| j d  }| _ t'|t(ƒ�r ||_)n||_*| +|¡ | j,d | j d }| j ¡ D ](}||d d d -|d ¡ d 7 }�q.|d7 }|| j. /¡ 7 }| 0|¡ t# 1d| j¡ | j 2| ¡ | j3j4 5¡  �nXg | _6| jj7| _7| j ¡ D ]X\}}d|k�rÒ�q¼|D ]:}	| ¡ dk�rút8|	 d
¡ƒ| _7n| j6 9| ¡ |	f¡ �qÖ�q¼t# 1d| j,| j¡ | j. :dd¡ t;| jj<| d	| j= d¡d  d
¡| j, d
¡t8| j d
¡ƒ| j| j7| j| j| j6| j| jdœƒV | _>| j>d k�s¬| j.j?�r²W d S | jj@}
| j. /|
¡}tA|ƒ|
k  }d||d œ}| j> B|¡ |�sº�qú�qºW n2 tCk
�r.   t# DtE F¡ ¡ |  dd!d"¡ Y nX d S )#Ni�  s   Bad RequestzInvalid header names   Upgrader   ÚhostÚportÚhttpsr   Úasciió   /zInvalid characters in pathó    ó   ?r	   zInvalid query strings	   websocketéô  z!Could not make WebSocket protocoló    s    HTTP/1.1
s   : ó   ,s   
z#Upgraded connection %s to WebSocketó   _s   daphne-root-pathzHTTP %s request for %séÿÿÿÿ)ÚtypeÚhttp_versionÚmethodÚpathÚraw_pathÚ	root_pathÚschemeÚquery_stringÚheadersÚclientr   zhttp.request)r/   ÚbodyÚ	more_bodyó   Internal Server ErrorzDaphne HTTP processing error)GÚtimeÚrequest_startZrequestHeadersZgetAllRawHeadersr
   Ú	fullmatchÚbasic_errorÚ	hasHeaderZgetRawHeadersÚhasattrr8   Ústrr#   r$   r   r   ZisSecureZclient_schemer   Zproxy_forwarded_address_headerr   Zproxy_forwarded_port_headerZproxy_forwarded_proto_headerr2   ÚdecodeÚUnicodeDecodeErrorr6   ÚuriÚsplitÚlowerZ
ws_factoryÚbuildProtocolÚ	transportZgetPeerÚsetResponseCoder   ÚwarnÚfinishZ_raw_query_stringÚ
isinstancer   ZwrappedProtocolÚprotocolZmakeConnectionr1   ÚjoinÚcontentÚreadZdataReceivedÚdebugÚprotocol_disconnectedr   Z_networkProducerZresumeProducingZclean_headersr4   r   ÚappendÚseekr   Zcreate_applicationZclientprotor   ÚclosedZrequest_buffer_sizeÚlenÚ
put_nowaitr   r   r   r   )r   ÚnameÚ_Zupgrade_headerrN   rI   ÚdataÚhÚvaluesÚvalueÚbuffer_sizeÚchunkr:   Úpayloadr!   r!   r"   ÚprocessD   sÖ    


ú	

ÿ


&


ÿ
òýý  ÿzWebRequest.processc                 C   s:   | j r|  ¡  t d| j¡ tj | |¡ | j 	| ¡ dS )ú3
        Cleans up reply channel on close.
        zHTTP disconnect for %sN)
r   Úsend_disconnectr   rR   r   r   r   ÚconnectionLostr   rS   )r   Úreasonr!   r!   r"   re   Õ   s
    zWebRequest.connectionLostc                 C   s8   | j r|  ¡  t d| j¡ tj | ¡ | j 	| ¡ dS )rc   zHTTP close for %sN)
r   rd   r   rR   r   r   r   rL   r   rS   ©r   r!   r!   r"   rL   ß   s
    zWebRequest.finishc                 C   sì  | j s| jdkrdS d|kr$tdƒ‚|d dkrÆ| jr>tdƒ‚d| _d|krTtdƒ‚|  |d ¡ | d	i ¡D ]\}}| j ||¡ qn| jj	r®| j 
d
¡s®|  d| jj	 ¡ ¡ t d|d | j¡ �n"|d dk�rØ| jsêtd|d  ƒ‚tj | | dd¡¡ | dd¡�sÈ|  ¡  t d| j¡ z| j d¡}W n  tk
�rT   t| jƒ}Y nX zJ| j dd|| j| j dd¡| j�rŠdt| jƒ nd|  ¡ | jdœ¡ W n$ tk
�rÄ   t t  !¡ ¡ Y nX nt d| j¡ ntd|d  ƒ‚dS )z1
        Handles a reply from the client
        Nr/   zMessage has no type definedúhttp.response.startz&HTTP response has already been startedTÚstatusz<Specifying a status code is required for a Response message.r7   r   s   serverzHTTP %s response started for %súhttp.response.bodyz1HTTP response has not yet been started but got %sr9   r(   r:   FzHTTP response complete for %sr&   r   ZcompleteÚreplacez%s:%s)r2   ri   r1   r8   Z
time_takenÚsizezHTTP response chunk for %szCannot handle message type %s!)"Úfinishedr   Ú
ValueErrorr   rJ   ÚgetZresponseHeadersZaddRawHeaderr   Zserver_namer@   Z	setHeaderÚencoder   rR   r   r   r   ÚwriterL   rE   rC   rD   ÚreprZ
log_actionÚcoder1   ÚtupleÚdurationZ
sentLengthr   r   r   r   )r   ÚmessageÚheaderr^   rE   r!   r!   r"   Úhandle_replyë   sn    ÿ  ÿÿÿÿöýzWebRequest.handle_replyc                 C   s   |   ddd¡ dS )zF
        Called by the server when our application tracebacks
        r*   r;   zException inside application.N)r?   )r   Ú	exceptionr!   r!   r"   Úhandle_exception1  s    zWebRequest.handle_exceptionc                 C   sD   | j jr@|  ¡ | j jkr@| jr2t d¡ |  ¡  n|  ddd¡ dS )zK
        Called periodically to see if we should timeout something
        z,Application timed out while sending responsei÷  s   Service Unavailablez0Application failed to respond within time limit.N)r   Zhttp_timeoutru   r   r   ÚwarningrL   r?   rg   r!   r!   r"   Úcheck_timeouts7  s    

ýzWebRequest.check_timeoutsc                 C   s   | j r| j ddi¡ dS )z_
        Sends a http.disconnect message.
        Useful only really for long-polling.
        r/   zhttp.disconnectN)r2   r   rX   rg   r!   r!   r"   rd   I  s    zWebRequest.send_disconnectc                 C   s   t | dƒsdS t ¡ | j S )zB
        Returns the time since the start of the request.
        r=   r   )rA   r<   r=   rg   r!   r!   r"   ru   R  s    
zWebRequest.durationc                 C   sL   |   d|dgdœ¡ |   d| jt|ƒd | d¡ |dœ  d¡d	œ¡ d
S )zF
        Responds with a server-level error page (very basic)
        rh   )s   Content-Types   text/html; charset=utf-8)r/   ri   r7   rj   r   r&   )Útitler9   Úutf8)r/   r9   N)rx   Úerror_templaterB   rC   rp   )r   ri   Zstatus_textr9   r!   r!   r"   r?   Z  s$    ýÿþÿÿúþÿzWebRequest.basic_errorc                 C   s   t t| ƒƒS ©N)ÚhashÚidrg   r!   r!   r"   Ú__hash__r  s    zWebRequest.__hash__c                 C   s   t | ƒt |ƒkS r€   )r‚   )r   Úotherr!   r!   r"   Ú__eq__u  s    zWebRequest.__eq__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rk   r   r   r   rb   re   rL   rx   rz   r|   rd   ru   r?   rƒ   r…   r!   r!   r!   r"   r      s:   	 î ì ë êÿ
 
F	r   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚHTTPFactoryzÍ
    Factory which takes care of tracking which protocol
    instances or request instances are responsible for which
    named response channels, so incoming messages can be
    routed appropriately.
    c                 C   s   t j | ¡ || _d S r€   )r   rŠ   r   r   )r   r   r!   r!   r"   r   ‚  s    zHTTPFactory.__init__c                 C   sH   zt j | |¡}t|_|W S  tk
rB   t dt 	¡  ¡ ‚ Y nX dS )zŠ
        Builds protocol instances. This override is used to ensure we use our
        own Request object instead of the default.
        zCannot build protocol: %sN)
r   rŠ   rH   r   ZrequestFactoryr   r   r   r   r   )r   ÚaddrrN   r!   r!   r"   rH   †  s    zHTTPFactory.buildProtocolc                 C   s   dg}t jr| dd¡ |S )a)  
        Protocols this server can speak after ALPN negotiation. Currently that
        is HTTP/1.1 and optionally HTTP/2. Websockets cannot be negotiated
        using ALPN, so that doesn't go here: anyone wanting websockets will
        negotiate HTTP/1.1 and then do the upgrade dance.
        s   http/1.1r   s   h2)r   Z
H2_ENABLEDÚinsert)r   ZbaseProtocolsr!   r!   r"   ÚacceptableProtocols”  s    zHTTPFactory.acceptableProtocolsN)r†   r‡   rˆ   r‰   r   rH   r�   r!   r!   r!   r"   rŠ   y  s   rŠ   )Úloggingr<   r   Úurllib.parser   Ztwisted.internet.deferr   r   Ztwisted.internet.interfacesr   Ztwisted.protocols.policiesr   Ztwisted.webr   Zzope.interfacer   Úutilsr
   r   Ú	getLoggerr†   r   r   r   rŠ   r!   r!   r!   r"   Ú<module>   s   
  j