o
    Óó·iLN  ã                   @   sÐ   d Z ddlmZmZ ddlmZ ddlmZmZm	Z	m
Z
mZ ddlmZ ddlmZ ddlmZ G dd	„ d	eƒZG d
d„ dƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ dƒZG dd„ deƒZdS )z 
Test for L{twisted.web.proxy}.
é    )ÚMemoryReactorÚ StringTransportWithDisconnection)ÚTestCase)ÚProxyClientÚProxyClientFactoryÚProxyRequestÚReverseProxyRequestÚReverseProxyResource)ÚResource)ÚSite©ÚDummyRequestc                   @   s@   e 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 )ÚReverseProxyResourceTestsz,
    Tests for L{ReverseProxyResource}.
    c                 C   sÂ   t ƒ }tƒ }tddd|ƒ}| d|¡ t|ƒ}tƒ }| d¡}| |¡ |  |j	d¡ | 
d| d ¡ |j\\}	}
}}}|  |	d¡ |  |
d¡ |  |t¡ |  |j|¡ |  |jd d	¡ dS )
z›
        Check that a request pointing at C{uri} produce a new proxy connection,
        with the path of this request pointing at C{expectedURI}.
        ú	127.0.0.1éÒ  ó   /paths   indexNs   GET s     HTTP/1.1
Accept: text/html

ó   hosts   127.0.0.1:1234)r
   r   r	   ZputChildr   r   ÚbuildProtocolÚmakeConnectionZ
addCleanupÚconnectionLostÚdataReceivedÚ
tcpClientsÚassertEqualÚassertIsInstancer   ÚrestÚheaders)ÚselfÚuriÚexpectedURIÚrootÚreactorÚresourceÚsiteÚ	transportÚchannelÚhostÚportÚfactoryÚ_timeoutZ
_bind_addr© r)   úaC:\Users\psant\Downloads\PAF backend\school\venv\Lib\site-packages\twisted/web/test/test_proxy.pyÚ_testRender   s    

z%ReverseProxyResourceTests._testRenderc                 C   ó   |   dd¡S )z˜
        Test that L{ReverseProxyResource.render} initiates a connection to the
        given server with a L{ProxyClientFactory} as parameter.
        s   /indexr   N©r+   ©r   r)   r)   r*   Útest_render8   ó   z%ReverseProxyResourceTests.test_renderc                 C   r,   )zÆ
        Test that L{ReverseProxyResource.render} will instantiate a child
        resource that will initiate a connection to the given server
        requesting the apropiate url subpath.
        s   /index/page1s   /path/page1Nr-   r.   r)   r)   r*   Útest_render_subpage?   ó   z-ReverseProxyResourceTests.test_render_subpagec                 C   r,   )zr
        Test that L{ReverseProxyResource.render} passes query parameters to the
        created factory.
        s   /index?foo=bars   /path?foo=barNr-   r.   r)   r)   r*   Útest_renderWithQueryG   r0   z.ReverseProxyResourceTests.test_renderWithQueryc                 C   sj   t ƒ }tddd|ƒ}| dd¡}|  |t¡ |  |jd¡ |  |jd¡ |  |jd¡ |  |j	|j	¡ dS )a  
        The L{ReverseProxyResource.getChild} method should return a resource
        instance with the same class as the originating resource, forward
        port, host, and reactor values, and update the path value with the
        value passed.
        r   r   r   ó   fooNs	   /path/foo)
r   r	   ÚgetChildr   r   Úpathr&   r%   ZassertIdenticalr    )r   r    r!   Úchildr)   r)   r*   Útest_getChildN   s   z'ReverseProxyResourceTests.test_getChildc                 C   s*   t dddƒ}| dd¡}|  |jd¡ dS )zu
        The L{ReverseProxyResource} return by C{getChild} has a path which has
        already been quoted.
        r   r   r   s    /%Ns   /path/%20%2F%25)r	   r5   r   r6   )r   r!   r7   r)   r)   r*   Útest_getChildWithSpecial_   s   z2ReverseProxyResourceTests.test_getChildWithSpecialN)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   r/   r1   r3   r8   r9   r)   r)   r)   r*   r      s    r   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚDummyChannelzÙ
    A dummy HTTP channel, that does nothing but holds a transport and saves
    connection lost.

    @ivar transport: the transport used by the client.
    @ivar lostReason: the reason saved at connection lost.
    c                 C   s   || _ d| _dS )z4
        Hold a reference to the transport.
        N)r#   Ú
lostReason)r   r#   r)   r)   r*   Ú__init__r   s   
zDummyChannel.__init__c                 C   s
   || _ dS )z;
        Keep track of the connection lost reason.
        N)r?   )r   Úreasonr)   r)   r*   r   y   ó   
zDummyChannel.connectionLostc                 C   ó
   | j  ¡ S )z:
        Get peer information from the transport.
        N)r#   ÚgetPeerr.   r)   r)   r*   rD      rB   zDummyChannel.getPeerc                 C   rC   )z:
        Get host information from the transport.
        N)r#   ÚgetHostr.   r)   r)   r*   rE   …   rB   zDummyChannel.getHostN)r:   r;   r<   r=   r@   r   rD   rE   r)   r)   r)   r*   r>   i   s    r>   c                   @   sš   e Zd ZdZdd„ Zdd„ Zd&d	d
„Zdd„ Zdd„ Zdd„ Z	dd„ Z
			d'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 )(ÚProxyClientTestsz#
    Tests for L{ProxyClient}.
    c                 C   s:   |  d¡\}}|  d¡}| d¡}|tdd„ |D ƒƒ|fS )aC  
        Parse the headers out of some web content.

        @param content: Bytes received from a web server.
        @return: A tuple of (requestLine, headers, body). C{headers} is a dict
            of headers, C{requestLine} is the first line (e.g. "POST /foo ...")
            and C{body} is whatever is left.
        s   

ó   
r   c                 s   s   � | ]}|  d ¡V  qdS )ó   : N)Úsplit)Ú.0Úheaderr)   r)   r*   Ú	<genexpr>�   s   € z4ProxyClientTests._parseOutHeaders.<locals>.<genexpr>N)rI   ÚpopÚdict)r   Úcontentr   ÚbodyÚrequestLiner)   r)   r*   Ú_parseOutHeaders‘   s   	

z!ProxyClientTests._parseOutHeadersc                 C   s   t |ƒS )z�
        Make a dummy request object for the URL path.

        @param path: A URL path, beginning with a slash.
        @return: A L{DummyRequest}.
        Nr   )r   r6   r)   r)   r*   ÚmakeRequestŸ   s   zProxyClientTests.makeRequestó   GETNó    c                 C   s,   |du rddi}d|j  }t||d|||ƒS )a´  
        Make a L{ProxyClient} object used for testing.

        @param request: The request to use.
        @param method: The HTTP method to use, GET by default.
        @param headers: The HTTP headers to use expressed as a dict. If not
            provided, defaults to {'accept': 'text/html'}.
        @param requestBody: The body of the request. Defaults to the empty
            string.
        @return: A L{ProxyClient}
        Nó   acceptó	   text/htmló   /ó   HTTP/1.0)Zpostpathr   )r   ÚrequestÚmethodr   ÚrequestBodyr6   r)   r)   r*   ÚmakeProxyClient¨   s   
z ProxyClientTests.makeProxyClientc                 C   s   t ƒ }||_| |¡ |S )z»
        Connect a proxy client to a L{StringTransportWithDisconnection}.

        @param proxyClient: A L{ProxyClient}.
        @return: The L{StringTransportWithDisconnection}.
        N)r   Úprotocolr   )r   ÚproxyClientZclientTransportr)   r)   r*   ÚconnectProxy¹   s   
zProxyClientTests.connectProxyc                 C   s@   |   |¡ |j ¡ }|  |¡\}}}|  ||¡ |  ||¡ |S )a`  
        Assert that C{proxyClient} sends C{headers} when it connects.

        @param proxyClient: A L{ProxyClient}.
        @param requestLine: The request line we expect to be sent.
        @param headers: A dict of headers we expect to be sent.
        @return: If the assertion is successful, return the request body as
            bytes.
        N)r`   r#   ÚvaluerR   r   )r   r_   rQ   r   ZrequestContentZreceivedLineÚreceivedHeadersrP   r)   r)   r*   ÚassertForwardsHeadersÅ   s   


z&ProxyClientTests.assertForwardsHeadersc           	      C   s^   dt |ƒ d¡ d | g}|D ]\}}|D ]}| |d | ¡ qq| d|g¡ d |¡S )Ns	   HTTP/1.0 Úasciió    rH   rU   rG   )ÚstrÚencodeÚappendÚextendÚjoin)	r   ÚcodeÚmessager   rP   ÚlinesrK   Úvaluesra   r)   r)   r*   ÚmakeResponseBytesÖ   s   ÿ
z"ProxyClientTests.makeResponseBytesc                 C   sj   |   |j|¡ |   |j|¡ t|j ¡ ƒ}| ¡  |dd… }| ¡  |   ||¡ |   d |j¡|¡ dS )aK  
        Assert that C{request} has forwarded a response from the server.

        @param request: A L{DummyRequest}.
        @param code: The expected HTTP response code.
        @param message: The expected HTTP message.
        @param headers: The expected HTTP headers.
        @param body: The expected response body.
        NrU   )	r   ÚresponseCodeÚresponseMessageÚlistÚresponseHeadersÚgetAllRawHeadersÚsortrj   Úwritten)r   rZ   rk   rl   r   rP   rb   ÚexpectedHeadersr)   r)   r*   ÚassertForwardsResponseÞ   s   
z'ProxyClientTests.assertForwardsResponseTc                 C   s˜   |   d¡}|  ||ddi|¡}	|  |	|d dddœ¡}
|  |
|¡ |	 |  ||||¡¡ |  |||||¡ |r<|	j ¡  |  	|	jj
¡ |  |jd¡ dS )	z‹
        Build a fake proxy connection, and send C{data} over it, checking that
        it's forwarded to the originating request.
        r4   rV   rW   s    /foo HTTP/1.0ó   close)ó
   connectionrV   é   N)rS   r]   rc   r   r   ro   rx   r#   ÚloseConnectionZassertFalseÚ	connectedÚfinished)r   rk   rl   r   rP   r[   r\   r|   rZ   ÚclientZreceivedBodyr)   r)   r*   Ú_testDataForwardñ   s    
ÿý
z!ProxyClientTests._testDataForwardc                 C   s   |   dddddgfgd¡S )zÃ
        When connected to the server, L{ProxyClient} should send the saved
        request, with modifications of the headers, and then forward the result
        to the parent request.
        éÈ   ó   OKó   Fooó   bars   bazó   Some data
N©r€   r.   r)   r)   r*   Útest_forward  s   ÿzProxyClientTests.test_forwardc                 C   s   |   ddddgfgddd¡S )	z~
        Try to post content in the request, and check that the proxy client
        forward the body of the request.
        r�   r‚   rƒ   r„   r…   ó   POSTó   Some contentNr†   r.   r)   r)   r*   Útest_postData'  s   ÿzProxyClientTests.test_postDatac                 C   s   |   ddg d¡S )z’
        If the response contains a status with a message, it should be
        forwarded to the parent request with all the information.
        i”  s	   Not FoundrU   Nr†   r.   r)   r)   r*   Útest_statusWithMessage0  ó   z'ProxyClientTests.test_statusWithMessagec                 C   s*   d}|   dddtt|ƒƒ d¡gfg|¡S )z�
        If the response contains a I{Content-Length} header, the inbound
        request object should still only have C{finish} called on it once.
        ó   foo bar bazr�   r‚   ó   Content-Lengthrd   N©r€   rf   Úlenrg   ©r   Údatar)   r)   r*   Útest_contentLength7  s   ÿz#ProxyClientTests.test_contentLengthc                 C   s.   d}| j dddtt|ƒƒ d¡gfg|dd�S )	zŸ
        If the response contains a I{Content-Length} header, the outgoing
        connection is closed when all response body data has been received.
        r�   r�   r‚   rŽ   rd   F)r|   Nr�   r‘   r)   r)   r*   Útest_losesConnectionA  s   ûz%ProxyClientTests.test_losesConnectionc                 C   s0   t ddddddœddƒ}|  |jdd	d
œ¡ dS )z®
        The headers given at initialization should be modified:
        B{proxy-connection} should be removed if present, and B{connection}
        should be added.
        rT   ó   /foorY   rW   r4   )rV   s   proxy-connectionrU   Nry   ©rV   rz   )r   r   r   )r   r   r)   r)   r*   Útest_headersCleanupsO  s   úÿz%ProxyClientTests.test_headersCleanupsc                 C   sF   ddddœ}|  ¡ }d|d< |d= tddd	|d
dƒ}|  |d|¡ dS )z¶
        The proxy doesn't really know what to do with keepalive things from
        the remote server, so we stomp over any keepalive header we get from
        the client.
        rW   s   300ó
   keep-alive)rV   r˜   rz   ry   rz   rT   r•   rY   rU   Ns   GET /foo HTTP/1.0)Úcopyr   rc   )r   r   rw   r   r)   r)   r*   Útest_keepaliveNotForwardeda  s   ýz+ProxyClientTests.test_keepaliveNotForwardedc                 C   s    |   d¡}|j ddg¡ |j ddg¡ |j ddg¡ | j|dd	id
�}|  |¡ dgdgdgdœ}| |  dd| ¡ d¡¡ |  |ddt	| ¡ ƒd¡ dS )zÞ
        L{server.Request} within the proxy sets certain response headers by
        default. When we get these headers back from the remote server, the
        defaults are overridden rather than simply appended.
        r4   s   servers   old-bars   dates   old-bazs   content-types   old/quxrV   rW   )r   r„   s
   2010-01-01s   application/x-baz)s   Servers   Dateó   Content-Typer�   r‚   rU   N)
rS   rs   ZsetRawHeadersr]   r`   r   ro   Úitemsrx   rr   )r   rZ   r   r   r)   r)   r*   Útest_defaultHeadersOverriddenr  s   

ýz.ProxyClientTests.test_defaultHeadersOverridden)rT   NrU   )rT   rU   T)r:   r;   r<   r=   rR   rS   r]   r`   rc   ro   rx   r€   r‡   rŠ   r‹   r“   r”   r—   rš   r�   r)   r)   r)   r*   rF   Œ   s*    
	
ø,
	
rF   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚProxyClientFactoryTestsz*
    Tests for L{ProxyClientFactory}.
    c                 C   sŒ   t dgƒ}tdddddid|ƒ}| dd¡ |  |jd	¡ |  |jd
¡ |  t|j ¡ ƒddgfg¡ |  d 	|j
¡d¡ |  |jd¡ dS )zƒ
        Check that L{ProxyClientFactory.clientConnectionFailed} produces
        a B{501} response to the parent request.
        r4   rT   r•   rY   rV   rW   Ú Niõ  s   Gateway errorr›   rU   s   <H1>Could not connect</H1>r{   )r   r   ZclientConnectionFailedr   rp   rq   rr   rs   rt   rj   rv   r~   )r   rZ   r'   r)   r)   r*   Útest_connectionFailedŒ  s   
ÿ
þz-ProxyClientFactoryTests.test_connectionFailedc                 C   sn   t dddddiddƒ}| d¡}|  |t¡ |  |jd¡ |  |jd¡ |  |jd¡ |  |jddd	œ¡ dS )
zŸ
        L{ProxyClientFactory.buildProtocol} should produce a L{ProxyClient}
        with the same values of attributes (with updates on the headers).
        rT   r•   rY   rV   rW   s	   Some dataNry   r–   )	r   r   r   r   r   Úcommandr   r’   r   )r   r'   Úprotor)   r)   r*   Útest_buildProtocol   s   ÿ
ÿz*ProxyClientFactoryTests.test_buildProtocolN)r:   r;   r<   r=   r    r£   r)   r)   r)   r*   rž   ‡  s    rž   c                   @   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 )ÚProxyRequestTestsz$
    Tests for L{ProxyRequest}.
    rT   rU   c           
      C   sþ   t ƒ }t|ƒ}tƒ }t|d|ƒ}| t|ƒ¡ | |¡ | |d| d¡ |  t|j	ƒd¡ |  |j	d d d¡ |  |j	d d d¡ |j	d d }	|  
|	t¡ |  |	j|¡ |  |	jd¡ |  |	jd	d
i¡ |  |	j|¡ |  |	j|¡ |  |	j|¡ dS )z…
        Build a request pointing at C{uri}, and check that a proxied request
        is created, pointing a C{expectedURI}.
        Fs   http://example.comrY   r{   r   úexample.coméP   é   r   ó   example.comN)r   r>   r   r   Ú	gotLengthr�   ZhandleContentChunkÚrequestReceivedr   r   r   r   r¡   Úversionr   r’   r   Zfather)
r   r   r   r[   r’   r#   r$   r    rZ   r'   r)   r)   r*   Ú_testProcess·  s$   
zProxyRequestTests._testProcessc                 C   s   |   dd¡S )a�  
        L{ProxyRequest.process} should create a connection to the given server,
        with a L{ProxyClientFactory} as connection factory, with the correct
        parameters:
            - forward comment, version and data values
            - update headers with the B{host} value
            - remove the host from the URL
            - pass the request as parent request
        ó   /foo/barN©r¬   r.   r)   r)   r*   Útest_processÑ  s   
zProxyRequestTests.test_processc                 C   r,   )z£
        If the incoming request doesn't contain a slash,
        L{ProxyRequest.process} should add one when instantiating
        L{ProxyClientFactory}.
        rU   rX   Nr®   r.   r)   r)   r*   Ú test_processWithoutTrailingSlashÝ  r2   z2ProxyRequestTests.test_processWithoutTrailingSlashc                 C   s   |   dddd¡S )zl
        L{ProxyRequest.process} should be able to retrieve request body and
        to forward it.
        r­   rˆ   r‰   Nr®   r.   r)   r)   r*   Útest_processWithDataå  rŒ   z&ProxyRequestTests.test_processWithDatac                 C   sz   t ƒ }t|ƒ}tƒ }t|d|ƒ}| d¡ | ddd¡ |  t|jƒd¡ |  |jd d d¡ |  |jd d d¡ d	S )
z˜
        Check that L{ProxyRequest.process} correctly parse port in the incoming
        URL, and create an outgoing connection with this port.
        Fr   rT   s   http://example.com:1234/foo/barrY   r{   r¥   r   N)	r   r>   r   r   r©   rª   r   r�   r   )r   r#   r$   r    rZ   r)   r)   r*   Útest_processWithPortì  s   
z&ProxyRequestTests.test_processWithPortN)rT   rU   )	r:   r;   r<   r=   r¬   r¯   r°   r±   r²   r)   r)   r)   r*   r¤   ²  s    
r¤   c                   @   ó   e Zd ZdZdd„ ZdS )ÚDummyFactoryz>
    A simple holder for C{host} and C{port} information.
    c                 C   s   || _ || _d S )N)r%   r&   )r   r%   r&   r)   r)   r*   r@     s   
zDummyFactory.__init__N)r:   r;   r<   r=   r@   r)   r)   r)   r*   r´   þ  ó    r´   c                   @   r³   )ÚReverseProxyRequestTestsz+
    Tests for L{ReverseProxyRequest}.
    c                 C   s²   t ƒ }t|ƒ}tƒ }t|d|ƒ}tddƒ|_| d¡ | ddd¡ |  t	|j
ƒd¡ |  |j
d d d¡ |  |j
d d d¡ |j
d d	 }|  |t¡ |  |jd
di¡ dS )a  
        L{ReverseProxyRequest.process} should create a connection to its
        factory host/port, using a L{ProxyClientFactory} instantiated with the
        correct parameters, and particularly set the B{host} header to the
        factory host.
        Fr¥   r   r   rT   r­   rY   r{   r§   r   r¨   N)r   r>   r   r   r´   r'   r©   rª   r   r�   r   r   r   r   )r   r#   r$   r    rZ   r'   r)   r)   r*   r¯     s   
z%ReverseProxyRequestTests.test_processN)r:   r;   r<   r=   r¯   r)   r)   r)   r*   r¶     rµ   r¶   N)r=   Ztwisted.internet.testingr   r   Ztwisted.trial.unittestr   Ztwisted.web.proxyr   r   r   r   r	   Ztwisted.web.resourcer
   Ztwisted.web.serverr   Ztwisted.web.test.test_webr   r   r>   rF   rž   r¤   r´   r¶   r)   r)   r)   r*   Ú<module>   s   S# |+L
