o
    Óó·i“&  ã                   @   sÔ   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	„ d	eƒZG d
d„ de	ƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZdS )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                   @   sD   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dS )Ú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                 C   sD   || _ || _|| _d|v r|d= d|d< | dd ¡ || _|| _d S )Ns   proxy-connections   closes
   connections
   keep-alive)ÚfatherÚcommandÚrestÚpopÚheadersÚdata©Úselfr   r   Úversionr   r   r   © r   úWC:\Users\psant\Downloads\PAF backend\school\venv\Lib\site-packages\twisted/web/proxy.pyÚ__init__)   s   
zProxyClient.__init__c                 C   sJ   |   | j| j¡ | j ¡ D ]
\}}|  ||¡ q|  ¡  | j | j	¡ d S ©N)
ZsendCommandr   r   r   ÚitemsZ
sendHeaderZ
endHeadersÚ	transportÚwriter   )r   ÚheaderÚvaluer   r   r   ÚconnectionMade4   s
   zProxyClient.connectionMadec                 C   s   | j  t|ƒ|¡ d S r   )r   ÚsetResponseCodeÚint)r   r   ÚcodeÚmessager   r   r   ÚhandleStatus;   s   zProxyClient.handleStatusc                 C   s6   |  ¡ dv r| jj ||g¡ d S | jj ||¡ d S )N)s   servers   dates   content-type)Úlowerr   ÚresponseHeadersÚsetRawHeadersÚaddRawHeader)r   Úkeyr   r   r   r   ÚhandleHeader>   s   zProxyClient.handleHeaderc                 C   s   | j  |¡ d S r   )r   r   )r   Úbufferr   r   r   ÚhandleResponsePartH   s   zProxyClient.handleResponsePartc                 C   s(   | j sd| _ | j ¡  | j ¡  dS dS )z�
        Finish the original request, indicating that the response has been
        completely written to it, and disconnect the outgoing transport.
        TN)Ú	_finishedr   Úfinishr   ZloseConnection)r   r   r   r   ÚhandleResponseEndK   s
   
ýzProxyClient.handleResponseEndN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r.   r   r    r%   r+   r-   r0   r   r   r   r   r      s    
r   c                   @   s,   e Zd ZdZeZdd„ Zdd„ Zdd„ ZdS )	ÚProxyClientFactoryz?
    Used by ProxyRequest to implement a simple web proxy.
    c                 C   s(   || _ || _|| _|| _|| _|| _d S r   )r   r   r   r   r   r   r   r   r   r   r   ^   s   
zProxyClientFactory.__init__c                 C   s    |   | j| j| j| j| j| j¡S r   )Úprotocolr   r   r   r   r   r   )r   Úaddrr   r   r   ÚbuildProtocolf   s   ÿz ProxyClientFactory.buildProtocolc                 C   s8   | j  dd¡ | j j dd¡ | j  d¡ | j  ¡  dS )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!   r'   r)   r   r/   )r   Z	connectorÚreasonr   r   r   ÚclientConnectionFailedk   s   z)ProxyClientFactory.clientConnectionFailedN)	r1   r2   r3   r4   r   r6   r   r8   r:   r   r   r   r   r5   V   s    r5   c                   @   s6   e Zd ZdZdeiZddiZeefdd„Z	dd„ Z
dS )	Ú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                 C   ó   t  | ||¡ || _d S r   ©r
   r   r   ©r   ZchannelZqueuedr   r   r   r   r   �   ó   
zProxyRequest.__init__c           
      C   sÖ   t | jƒ}|d }|d  d¡}| j| }d|v r$| d¡\}}t|ƒ}td|dd …  ƒ}|s4|d }| j| }|  ¡  	¡ }d|vrJ| 
d¡|d< | j dd¡ | j ¡ }|| j|| j||| ƒ}	| j |||	¡ d S )	Nr   é   Úasciiú:)ó    rD   é   ó   /ó   host)r   ÚuriÚdecodeÚportsÚsplitr"   r   Ú	protocolsÚgetAllHeadersÚcopyÚencodeÚcontentÚseekÚreadÚmethodÚclientprotor   Ú
connectTCP)
r   Úparsedr6   ÚhostÚportr   Úclass_r   ÚsÚclientFactoryr   r   r   Úprocess…   s$   



zProxyRequest.processN)r1   r2   r3   r4   r5   rL   rJ   r   r   r   r\   r   r   r   r   r;   v   s    r;   c                   @   ó   e Zd ZdZeZdS )Ú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)r1   r2   r3   r4   r;   ÚrequestFactoryr   r   r   r   r^   š   s    r^   c                   @   s*   e Zd ZdZeZeefdd„Zdd„ Z	dS )Ú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                 C   r=   r   r>   r?   r   r   r   r   º   r@   zReverseProxyRequest.__init__c                 C   sZ   | j  d| jj d¡g¡ |  | j| j| j|  	¡ | j
 ¡ | ¡}| j | jj| jj|¡ dS )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.
        rG   rB   N)ÚrequestHeadersr(   ÚfactoryrW   rO   ÚproxyClientFactoryClassrS   rH   rT   rM   rP   rR   r   rU   rX   )r   r[   r   r   r   r\   ¾   s   úzReverseProxyRequest.processN)
r1   r2   r3   r4   r5   rc   r   r   r   r\   r   r   r   r   r`   ¬   s
    r`   c                   @   r]   )ÚReverseProxyzo
    Implements a simple reverse proxy.

    For details of usage, see the file examples/reverse-proxy.py.
    N)r1   r2   r3   r4   r`   r_   r   r   r   r   rd   Ð   s    rd   c                   @   s0   e Zd ZdZeZefdd„Zdd„ Zdd„ Z	dS )	Ú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                 C   s&   t  | ¡ || _|| _|| _|| _dS )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   rW   rX   Úpathr   )r   rW   rX   rf   r   r   r   r   r   ë   s
   

zReverseProxyResource.__init__c                 C   s,   t | j| j| jd t|dd� d¡ | 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.
        rF   rD   )Úsafezutf-8N)re   rW   rX   rf   ÚurlquoterO   r   )r   rf   Úrequestr   r   r   ÚgetChild  s   üzReverseProxyResource.getChildc                 C   s¨   | j dkr	| j}nd| j| j f }|j d| d¡g¡ |j dd¡ t|jƒd }|r4| j	d | }n| j	}|  
|j||j| ¡ |j ¡ |¡}| j | j| j |¡ tS )	zJ
        Render a request by forwarding it to the proxied server.
        r<   z%s:%drG   rB   r   é   ó   ?N)rX   rW   ra   r(   rO   rP   rQ   r   rH   rf   rc   rS   rT   rM   rR   r   rU   r   )r   ri   rW   Úqsr   r[   r   r   r   Úrender  s&   
úzReverseProxyResource.renderN)
r1   r2   r3   r4   r5   rc   r   r   rj   rn   r   r   r   r   re   Ú   s    re   N)r4   Úurllib.parser   rh   r   r   Ztwisted.internetr   Ztwisted.internet.protocolr   Ztwisted.web.httpr   r   r	   r
   Ztwisted.web.resourcer   Ztwisted.web.serverr   r   r5   r;   r^   r`   rd   re   r   r   r   r   Ú<module>   s   7 $$
