Ë
    oj“&  ã                   óþ   — d Z ddlmZmZmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZ ddlmZ ddlmZ  G d„ d	e«      Z G d
„ de	«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Zy)aT  
Simplistic HTTP proxy support.

This comes in two main variants - the Proxy and the ReverseProxy.

When a Proxy is in use, a browser trying to connect to a server (say,
www.yahoo.com) will be intercepted by the Proxy, and the proxy will covertly
connect to the server, and return the result.

When a ReverseProxy is in use, the client connects directly to the ReverseProxy
(say, www.yahoo.com) which farms off the request to one of a pool of servers,
and returns the result.

Normally, a Proxy is used on the client end of an Internet connection, while a
ReverseProxy is used on the server end.
é    )ÚquoteÚurlparseÚ
urlunparse)Úreactor)ÚClientFactory)Ú_QUEUED_SENTINELÚHTTPChannelÚ
HTTPClientÚRequest)ÚResource)ÚNOT_DONE_YETc                   ó8   — e Zd ZdZdZd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
y	)
ÚProxyClientzµ
    Used by ProxyClientFactory to implement a simple web proxy.

    @ivar _finished: A flag which indicates whether or not the original request
        has been finished yet.
    Fc                 ó†   — || _         || _        || _        d|v r|d= d|d<   |j                  dd «       || _        || _        y )Ns   proxy-connections   closes
   connections
   keep-alive)ÚfatherÚcommandÚrestÚpopÚheadersÚdata©Úselfr   r   Úversionr   r   r   s          ú3/usr/lib/python3/dist-packages/twisted/web/proxy.pyÚ__init__zProxyClient.__init__)   sN   € ØˆŒØˆŒØˆŒ	Ø 'Ñ)ØÐ+Ð,Ø!)ˆ�ÑØ�‰�M 4Ô(ØˆŒØˆ�	ó    c                 ó"  — | j                  | j                  | j                  «       | j                  j	                  «       D ]  \  }}| j                  ||«       Œ | j                  «        | j                  j                  | j                  «       y ©N)
ÚsendCommandr   r   r   ÚitemsÚ
sendHeaderÚ
endHeadersÚ	transportÚwriter   )r   ÚheaderÚvalues      r   ÚconnectionMadezProxyClient.connectionMade4   sh   € Ø×Ñ˜Ÿ™ t§y¡yÔ1Ø!Ÿ\™\×/Ñ/Ó1ò 	+‰MˆF�EØ�O‰O˜F EÕ*ð	+à�‰ÔØ�‰×Ñ˜TŸY™YÕ'r   c                 óN   — | j                   j                  t        |«      |«       y r   )r   ÚsetResponseCodeÚint)r   r   ÚcodeÚmessages       r   ÚhandleStatuszProxyClient.handleStatus;   s   € Ø�‰×#Ñ#¤C¨£I¨wÕ7r   c                 óÄ   — |j                  «       dv r(| j                  j                  j                  ||g«       y | j                  j                  j	                  ||«       y )N)s   servers   dates   content-type)Úlowerr   ÚresponseHeadersÚsetRawHeadersÚaddRawHeader)r   Úkeyr&   s      r   ÚhandleHeaderzProxyClient.handleHeader>   sI   € ð
 �9‰9‹;Ð?Ñ?Ø�K‰K×'Ñ'×5Ñ5°c¸E¸7ÕCà�K‰K×'Ñ'×4Ñ4°S¸%Õ@r   c                 ó:   — | j                   j                  |«       y r   )r   r$   )r   Úbuffers     r   ÚhandleResponsePartzProxyClient.handleResponsePartH   s   € Ø�‰×Ñ˜&Õ!r   c                 ó”   — | j                   s<d| _         | j                  j                  «        | j                  j	                  «        yy)z�
        Finish the original request, indicating that the response has been
        completely written to it, and disconnect the outgoing transport.
        TN)Ú	_finishedr   Úfinishr#   ÚloseConnection)r   s    r   ÚhandleResponseEndzProxyClient.handleResponseEndK   s7   € ð
 �~Š~Ø!ˆDŒNØ�K‰K×ÑÔ Ø�N‰N×)Ñ)Õ+ð r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r9   r   r'   r-   r4   r7   r<   © r   r   r   r      s-   „ ñð €Iò	ò(ò8òAò"ó,r   r   c                   ó&   — e Zd ZdZeZd„ Zd„ Zd„ Zy)ÚProxyClientFactoryz?
    Used by ProxyRequest to implement a simple web proxy.
    c                 óX   — || _         || _        || _        || _        || _        || _        y r   )r   r   r   r   r   r   r   s          r   r   zProxyClientFactory.__init__^   s,   € ØˆŒØˆŒØˆŒ	ØˆŒØˆŒ	Øˆ�r   c                 ó¦   — | j                  | j                  | j                  | j                  | j                  | j
                  | j                  «      S r   )Úprotocolr   r   r   r   r   r   )r   Úaddrs     r   ÚbuildProtocolz ProxyClientFactory.buildProtocolf   s8   € Ø�}‰}Ø�L‰L˜$Ÿ)™) T§\¡\°4·<±<ÀÇÁÈDÏKÉKó
ð 	
r   c                 óò   — | j                   j                  dd«       | j                   j                  j                  dd«       | j                   j	                  d«       | j                   j                  «        y)zh
        Report a connection failure in a response to the incoming request as
        an error.
        iõ  s   Gateway errors   Content-Types	   text/htmls   <H1>Could not connect</H1>N)r   r)   r0   r2   r$   r:   )r   Ú	connectorÚreasons      r   ÚclientConnectionFailedz)ProxyClientFactory.clientConnectionFailedk   sV   € ð
 	�‰×#Ñ# CÐ)9Ô:Ø�‰×#Ñ#×0Ñ0°À,ÔOØ�‰×ÑÐ7Ô8Ø�‰×ÑÕr   N)	r=   r>   r?   r@   r   rF   r   rH   rL   rA   r   r   rC   rC   V   s   „ ñð
 €Hòò
ó
r   rC   c                   ó2   — e Zd ZdZdeiZddiZeefd„Z	d„ Z
y)ÚProxyRequestzÃ
    Used by Proxy to implement a simple web proxy.

    @ivar reactor: the reactor used to create connections.
    @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP}
    s   httpéP   c                 ó@   — t        j                  | ||«       || _        y r   ©r   r   r   ©r   ÚchannelÚqueuedr   s       r   r   zProxyRequest.__init__�   ó   € Ü×Ñ˜˜w¨Ô/Øˆ�r   c                 óf  — t        | j                  «      }|d   }|d   j                  d«      }| j                  |   }d|v r|j	                  d«      \  }}t        |«      }t        d|dd  z   «      }|s|dz   }| j                  |   }| j                  «       j                  «       }d|vr|j                  d«      |d<   | j                  j                  dd«       | j                  j                  «       } || j                  || j                  ||| «      }	| j                   j#                  |||	«       y )	Nr   é   Úasciiú:)r   r   é   ó   /ó   host)r   ÚuriÚdecodeÚportsÚsplitr*   r   Ú	protocolsÚgetAllHeadersÚcopyÚencodeÚcontentÚseekÚreadÚmethodÚclientprotor   Ú
connectTCP)
r   ÚparsedrF   ÚhostÚportr   Úclass_r   ÚsÚclientFactorys
             r   ÚprocesszProxyRequest.process…   s  € Ü˜$Ÿ(™(Ó#ˆØ˜!‘9ˆØ�a‰y×Ñ Ó(ˆØ�z‰z˜(Ñ#ˆØ�$‰;ØŸ™ C›‰JˆD�$Ü�t“9ˆDÜ˜* v¨a¨b zÑ1Ó2ˆÙØ˜$‘;ˆDØ—‘ Ñ)ˆØ×$Ñ$Ó&×+Ñ+Ó-ˆØ˜'Ñ!Ø#Ÿ{™{¨7Ó3ˆG�GÑØ�‰×Ñ˜!˜QÔØ�L‰L×ÑÓˆÙ˜tŸ{™{¨D°$×2BÑ2BÀGÈQÐPTÓUˆØ�‰×Ñ  d¨MÕ:r   N)r=   r>   r?   r@   rC   ra   r_   r   r   r   rq   rA   r   r   rN   rN   v   s,   „ ñð Ð,Ð-€IØ�bˆM€Eà'7Àó ó;r   rN   c                   ó   — e Zd ZdZeZy)ÚProxyao  
    This class implements a simple web proxy.

    Since it inherits from L{twisted.web.http.HTTPChannel}, to use it you
    should do something like this::

        from twisted.web import http
        f = http.HTTPFactory()
        f.protocol = Proxy

    Make the HTTPFactory a listener on a port as per usual, and you have
    a fully-functioning web proxy!
    N)r=   r>   r?   r@   rN   ÚrequestFactoryrA   r   r   rs   rs   š   s   „ ñð "�Nr   rs   c                   ó&   — e Zd ZdZeZeefd„Zd„ Z	y)ÚReverseProxyRequestal  
    Used by ReverseProxy to implement a simple reverse proxy.

    @ivar proxyClientFactoryClass: a proxy client factory class, used to create
        new connections.
    @type proxyClientFactoryClass: L{ClientFactory}

    @ivar reactor: the reactor used to create connections.
    @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP}
    c                 ó@   — t        j                  | ||«       || _        y r   rQ   rR   s       r   r   zReverseProxyRequest.__init__º   rU   r   c                 óÂ  — | j                   j                  d| j                  j                  j	                  d«      g«       | j                  | j                  | j                  | j                  | j                  «       | j                  j                  «       | «      }| j                  j                  | j                  j                  | j                  j                  |«       y)zµ
        Handle this request by connecting to the proxied server and forwarding
        it there, then forwarding the response back as the response to this
        request.
        r\   rX   N)ÚrequestHeadersr1   Úfactoryrl   rd   ÚproxyClientFactoryClassrh   r]   ri   rb   re   rg   r   rj   rm   )r   rp   s     r   rq   zReverseProxyRequest.process¾   s¤   € ð 	×Ñ×)Ñ)¨'°D·L±L×4EÑ4E×4LÑ4LÈWÓ4UÐ3VÔWØ×4Ñ4Ø�K‰KØ�H‰HØ×ÑØ×ÑÓ Ø�L‰L×ÑÓØó
ˆð 	�‰×Ñ §¡× 1Ñ 1°4·<±<×3DÑ3DÀmÕTr   N)
r=   r>   r?   r@   rC   r{   r   r   r   rq   rA   r   r   rv   rv   ¬   s   „ ñ	ð 1Ðà'7Àó óUr   rv   c                   ó   — e Zd ZdZeZy)ÚReverseProxyzo
    Implements a simple reverse proxy.

    For details of usage, see the file examples/reverse-proxy.py.
    N)r=   r>   r?   r@   rv   rt   rA   r   r   r}   r}   Ð   s   „ ñð )�Nr   r}   c                   ó*   — e Zd ZdZeZefd„Zd„ Zd„ Z	y)ÚReverseProxyResourceaØ  
    Resource that renders the results gotten from another server

    Put this resource in the tree to cause everything below it to be relayed
    to a different server.

    @ivar proxyClientFactoryClass: a proxy client factory class, used to create
        new connections.
    @type proxyClientFactoryClass: L{ClientFactory}

    @ivar reactor: the reactor used to create connections.
    @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP}
    c                 óf   — t        j                  | «       || _        || _        || _        || _        y)aU  
        @param host: the host of the web server to proxy.
        @type host: C{str}

        @param port: the port of the web server to proxy.
        @type port: C{port}

        @param path: the base path to fetch data from. Note that you shouldn't
            put any trailing slashes in it, it will be added automatically in
            request. For example, if you put B{/foo}, a request on B{/bar} will
            be proxied to B{/foo/bar}.  Any required encoding of special
            characters (such as " " or "/") should have been done already.

        @type path: C{bytes}
        N)r   r   rl   rm   Úpathr   )r   rl   rm   r�   r   s        r   r   zReverseProxyResource.__init__ë   s.   € ô  	×Ñ˜$ÔØˆŒ	ØˆŒ	ØˆŒ	Øˆ�r   c           	      ó®   — t        | j                  | j                  | j                  dz   t	        |d¬«      j                  d«      z   | j                  «      S )z¿
        Create and return a proxy resource with the same proxy configuration
        as this one, except that its path also contains the segment given by
        C{path} at the end.
        r[   r   )Úsafezutf-8)r   rl   rm   r�   Úurlquoterd   r   )r   r�   Úrequests      r   ÚgetChildzReverseProxyResource.getChild  sI   € ô $Ø�I‰IØ�I‰IØ�I‰I˜Ñœx¨°3Ô7×>Ñ>¸wÓGÑGØ�L‰Ló	
ð 	
r   c                 ó€  — | j                   dk(  r| j                  }nd| j                  | j                   fz  }|j                  j                  d|j	                  d«      g«       |j
                  j                  dd«       t        |j                  «      d   }|r| j                  dz   |z   }n| j                  }| j                  |j                  ||j                  |j                  «       |j
                  j                  «       |«      }| j                  j!                  | j                  | j                   |«       t"        S )zJ
        Render a request by forwarding it to the proxied server.
        rO   z%s:%dr\   rX   r   é   ó   ?)rm   rl   ry   r1   rd   re   rf   r   r]   r�   r{   rh   ri   rb   rg   r   rj   r   )r   r…   rl   Úqsr   rp   s         r   ÚrenderzReverseProxyResource.render  sÿ   € ð �9‰9˜Š?Ø—9‘9‰Dà˜dŸi™i¨¯©Ð3Ñ3ˆDØ×Ñ×,Ñ,¨W°t·{±{À7Ó7KÐ6LÔMØ�‰×Ñ˜Q Ô"Ü�g—k‘kÓ" 1Ñ%ˆÙØ—9‘9˜tÑ# bÑ(‰Dà—9‘9ˆDØ×4Ñ4Ø�N‰NØØ×ÑØ×!Ñ!Ó#Ø�O‰O× Ñ Ó"Øó
ˆð 	�‰×Ñ §	¡	¨4¯9©9°mÔDÜÐr   N)
r=   r>   r?   r@   rC   r{   r   r   r†   r‹   rA   r   r   r   r   Ú   s!   „ ñð 1Ðà18ó ò,
ór   r   N)r@   Úurllib.parser   r„   r   r   Útwisted.internetr   Útwisted.internet.protocolr   Útwisted.web.httpr   r	   r
   r   Útwisted.web.resourcer   Útwisted.web.serverr   r   rC   rN   rs   rv   r}   r   rA   r   r   ú<module>r’      s�   ðñ
÷" AÑ @å $Ý 3ß OÓ OÝ )Ý +ô4,�*ô 4,ôn˜ô ô@!;�7ô !;ôH"ˆKô "ô$!U˜'ô !UôH)�;ô )ôN˜8õ Nr   