U
    
W[^4                     @   s6  d Z ddlmZmZ ddg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 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m Z m!Z! ddl"m#Z# eeG dd de$Z%G dd dZ&G dd de$Z'eedddddde'j(e'_(G dd dej)Z*dS )z2
Helpers related to HTTP requests, used by tests.
    )divisionabsolute_importDummyChannelDummyRequest)BytesIO)implementerverify)
intToBytes)
deprecated)Version)Deferred)IPv4AddressIPv6Address)ISSLTransportIAddress)unittest)Headers)Resource)NOT_DONE_YETSessionSite)FOUNDc                   @   s   e Zd ZdZdS )NullAddressz/
    A null implementation of L{IAddress}.
    N)__name__
__module____qualname____doc__ r   r   @/usr/lib/python3/dist-packages/twisted/web/test/requesthelper.pyr       s   r   c                   @   s   e Zd ZG dd dZeeG dd deZee 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d Zdd Zdd ZdS )r   c                   @   sV   e Zd ZdZ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S )zDummyChannel.TCPP   FNc                 C   s,   |d krt ddd}|| _t | _g | _d S )NTCPz192.168.1.1i80  )r   _peerr   written	producersselfZpeerr   r   r   __init__-   s
    zDummyChannel.TCP.__init__c                 C   s   | j S N)r!   r%   r   r   r   getPeer4   s    zDummyChannel.TCP.getPeerc                 C   s(   t |tstd|f | j| d S )Nz+Can only write bytes to a transport, not %r)
isinstancebytes	TypeErrorr"   writer%   datar   r   r   r-   7   s    
zDummyChannel.TCP.writec                 C   s   |D ]}|  | qd S r'   )r-   )r%   iovecr/   r   r   r   writeSequence<   s    zDummyChannel.TCP.writeSequencec                 C   s   t dd| jS )Nr    z10.0.0.1)r   portr(   r   r   r   getHost@   s    zDummyChannel.TCP.getHostc                 C   s   | j ||f d S r'   )r#   appendr%   ZproducerZ	streamingr   r   r   registerProducerC   s    z!DummyChannel.TCP.registerProducerc                 C   s   d S r'   r   r(   r   r   r   unregisterProducerF   s    z#DummyChannel.TCP.unregisterProducerc                 C   s
   d| _ d S )NT)disconnectedr(   r   r   r   loseConnectionI   s    zDummyChannel.TCP.loseConnection)N)r   r   r   r2   r8   r&   r)   r-   r1   r3   r6   r7   r9   r   r   r   r   r    )   s   
r    c                   @   s   e Zd ZdS )zDummyChannel.SSLN)r   r   r   r   r   r   r   SSLM   s   r:   Nc                 C   s   |  || _d S r'   )r    	transportr$   r   r   r   r&   S   s    zDummyChannel.__init__c                 C   s   d S r'   r   )r%   requestr   r   r   requestDoneW   s    zDummyChannel.requestDonec                 C   sL   |d | d | d }|g}| dd |D  |d | j| d S )N       
c                 s   s"   | ]\}}|d  | d V  qdS )s   : r?   Nr   ).0namevaluer   r   r   	<genexpr>^   s    z,DummyChannel.writeHeaders.<locals>.<genexpr>)extendr4   r;   r1   )r%   versioncodereasonheadersZresponse_lineZheaderSequencer   r   r   writeHeaders[   s    

zDummyChannel.writeHeadersc                 C   s
   | j  S r'   )r;   r)   r(   r   r   r   r)   e   s    zDummyChannel.getPeerc                 C   s
   | j  S r'   )r;   r3   r(   r   r   r   r3   i   s    zDummyChannel.getHostc                 C   s   | j || d S r'   )r;   r6   r5   r   r   r   r6   m   s    zDummyChannel.registerProducerc                 C   s   | j   d S r'   )r;   r7   r(   r   r   r   r7   q   s    zDummyChannel.unregisterProducerc                 C   s   | j | d S r'   )r;   r-   r.   r   r   r   r-   u   s    zDummyChannel.writec                 C   s   | j | d S r'   )r;   r1   )r%   r0   r   r   r   r1   y   s    zDummyChannel.writeSequencec                 C   s   | j   d S r'   )r;   r9   r(   r   r   r   r9   }   s    zDummyChannel.loseConnectionc                 C   s   d S r'   r   r(   r   r   r   
endRequest   s    zDummyChannel.endRequestc                 C   s   t | j| jS r'   )r*   r;   r:   r(   r   r   r   isSecure   s    zDummyChannel.isSecure)N)r   r   r   r    r   r   r:   r   r   Zsiter&   r=   rI   r)   r3   r6   r7   r-   r1   r9   rJ   rK   r   r   r   r   r   (   s    $


c                   @   s   e Zd ZdZdZdZdZdd Zdd Zd2d	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d3dd Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd4d.d/Zd0d1 ZdS )5r   a  
    Represents a dummy or fake request. See L{twisted.web.server.Request}.

    @ivar _finishedDeferreds: L{None} or a C{list} of L{Deferreds} which will
        be called back with L{None} when C{finish} is called or which will be
        errbacked if C{processingFailed} is called.

    @type requestheaders: C{Headers}
    @ivar requestheaders: A Headers instance that stores values for all request
        headers.

    @type responseHeaders: C{Headers}
    @ivar responseHeaders: A Headers instance that stores values for all
        response headers.

    @type responseCode: C{int}
    @ivar responseCode: The response code which was passed to
        C{setResponseCode}.

    @type written: C{list} of C{bytes}
    @ivar written: The bytes which have been written to the request.
    s   http://dummy/s   GETNc                 C   s   d| _ | j r|  qdS )z
        Call an L{IPullProducer}'s C{resumeProducing} method in a
        loop until it unregisters itself.

        @param prod: The producer.
        @type prod: L{IPullProducer}

        @param s: Whether or not the producer is streaming.
           N)goZresumeProducing)r%   Zprodsr   r   r   r6      s    zDummyRequest.registerProducerc                 C   s
   d| _ d S )Nr   )rM   r(   r   r   r   r7      s    zDummyRequest.unregisterProducerc                 C   sf   g | _ g | _d| _|| _g | _d | _|p0td| | _i | _t	 | _
t	 | _d | _g | _d| _d| _d S )Nr   s   dummys   HTTP/1.0)Zsitepathr"   finishedpostpathZprepathsessionr   protoSessionargsr   requestHeadersresponseHeadersresponseCode_finishedDeferreds_serverNameZclientproto)r%   rP   rQ   clientr   r   r   r&      s    zDummyRequest.__init__c                 C   s,   i }| j  D ]\}}|d || < q|S )ah  
        Return dictionary mapping the names of all received headers to the last
        value received for each.

        Since this method does not return all header information,
        C{self.requestHeaders.getAllRawHeaders()} may be preferred.

        NOTE: This function is a direct copy of
        C{twisted.web.http.Request.getAllRawHeaders}.
        )rT   ZgetAllRawHeaderslower)r%   rH   kvr   r   r   getAllHeaders   s    zDummyRequest.getAllHeadersc                 C   s   | j | dgd S )aH  
        Retrieve the value of a request header.

        @type name: C{bytes}
        @param name: The name of the request header for which to retrieve the
            value.  Header names are compared case-insensitively.

        @rtype: C{bytes} or L{None}
        @return: The value of the specified request header.
        Nr   )rT   ZgetRawHeadersr[   )r%   rA   r   r   r   	getHeader   s    zDummyRequest.getHeaderc                 C   s   | j || dS )zJTODO: make this assert on write() if the header is content-length
        N)rU   addRawHeaderr%   rA   rB   r   r   r   	setHeader   s    zDummyRequest.setHeaderc                 C   s(   | j r| j S | jrtd| j| _ | j S )Nz8Session cannot be requested after data has been written.)rQ   r"   AssertionErrorrR   r(   r   r   r   
getSession   s
    zDummyRequest.getSessionc                 C   s,   | | }|tkrdS | | |   dS )a  
        Render the given resource as a response to this request.

        This implementation only handles a few of the most common behaviors of
        resources.  It can handle a render method that returns a string or
        C{NOT_DONE_YET}.  It doesn't know anything about the semantics of
        request methods (eg HEAD) nor how to set any particular headers.
        Basically, it's largely broken, but sufficient for some tests at least.
        It should B{not} be expanded to do all the same stuff L{Request} does.
        Instead, L{DummyRequest} should be phased out and L{Request} (or some
        other real code factored in a different way) used.
        N)renderr   r-   finish)r%   resourceresultr   r   r   re      s
    

zDummyRequest.renderc                 C   s"   t |tstd| j| d S )Nzwrite() only accepts bytes)r*   r+   r,   r"   r4   r.   r   r   r   r-     s    
zDummyRequest.writec                 C   s   t  }| j| |S )z
        Return a L{Deferred} which is called back with L{None} when the request
        is finished.  This will probably only work if you haven't called
        C{finish} yet.
        )r   rW   r4   )r%   rO   r   r   r   notifyFinish  s    zDummyRequest.notifyFinishc                 C   s:   | j d | _ | jdk	r6| j}d| _|D ]}|d q&dS )z}
        Record that the request is finished and callback and L{Deferred}s
        waiting for notification of this.
        rL   N)rO   rW   callback)r%   	observersobsr   r   r   rf     s    
zDummyRequest.finishc                 C   s.   | j dk	r*| j }d| _ |D ]}|| qdS )zK
        Errback and L{Deferreds} waiting for finish notification.
        N)rW   Zerrback)r%   rG   rk   rl   r   r   r   processingFailed*  s
    
zDummyRequest.processingFailedc                 C   s   |g| j |< d S r'   )rS   ra   r   r   r   addArg5  s    zDummyRequest.addArgc                 C   s*   | j rtdd| j  || _|| _dS )z{
        Set the HTTP status response code, but takes care that this is called
        before any data is written.
        z<Response code cannot be set after data has been written: %s.@@@@N)r"   rc   joinrV   ZresponseMessage)r%   rF   messager   r   r   setResponseCode9  s    zDummyRequest.setResponseCodec                 C   s   | j rtdd| j  d S )Nz<Last-Modified cannot be set after data has been written: %s.ro   r"   rc   rp   )r%   Zwhenr   r   r   setLastModifiedC  s    zDummyRequest.setLastModifiedc                 C   s   | j rtdd| j  d S )Nz3ETag cannot be set after data has been written: %s.ro   rs   )r%   tagr   r   r   setETagG  s    zDummyRequest.setETagc                 C   s   t | jttfr| jjS dS )z|
        Return the IPv4 address of the client which made this request, if there
        is one, otherwise L{None}.
        N)r*   rY   r   r   hostr(   r   r   r   getClientIPK  s    zDummyRequest.getClientIPc                 C   s   | j dkrt S | j S )z
        Return the L{IAddress} of the client that made this request.

        @return: an address.
        @rtype: an L{IAddress} provider.
        N)rY   r   r(   r   r   r   getClientAddressU  s    
zDummyRequest.getClientAddressc                 C   s   | j S )z
        Get a dummy hostname associated to the HTTP request.

        @rtype: C{bytes}
        @returns: a dummy hostname
        )rX   r(   r   r   r   getRequestHostnamea  s    zDummyRequest.getRequestHostnamec                 C   s   t dddS )zz
        Get a dummy transport's host.

        @rtype: C{IPv4Address}
        @returns: a dummy transport's host
        r    	127.0.0.1r   )r   r(   r   r   r   r3   k  s    zDummyRequest.getHostr   c                 C   sH   || _ |  rd}nd}||kr&|}n|d t| }| jd| dS )a_  
        Change the host and port the request thinks it's using.

        @type host: C{bytes}
        @param host: The value to which to change the host header.

        @type ssl: C{bool}
        @param ssl: A flag which, if C{True}, indicates that the request is
            considered secure (if C{True}, L{isSecure} will return C{True}).
        i  r      :s   hostN)Z	_forceSSLrK   r	   rT   r`   )r%   rw   r2   ZssldefaultZ
hostHeaderr   r   r   setHostu  s    zDummyRequest.setHostc                 C   s   |  t | d| dS )zu
        Utility function that does a redirect.

        The request should have finish() called after this.
        s   locationN)rr   r   rb   )r%   Zurlr   r   r   redirect  s    
zDummyRequest.redirect)NN)N)r   )r   r   r   r   ZurimethodrY   r6   r7   r&   r^   r_   rb   rd   re   r-   ri   rf   rm   rn   rr   rt   rv   rx   ry   rz   r3   r~   r   r   r   r   r   r      s4   






ZTwisted      ry   )Zreplacementc                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )DummyRequestTestsz$
    Tests for L{DummyRequest}.
    c                 C   s^   t g }|  | j| jgd}| dt| |\}| |dt | |dd dS )zp
        L{DummyRequest.getClientIP} is deprecated in favor of
        L{DummyRequest.getClientAddress}
        )ZoffendingFunctionsrL   categoryrq   z}twisted.web.test.requesthelper.DummyRequest.getClientIP was deprecated in Twisted 18.4.0; please use getClientAddress insteadN)r   rx   ZflushWarningstest_getClientIPDeprecatedassertEquallengetDeprecationWarning)r%   r<   warningsZwarningr   r   r   r     s    z,DummyRequestTests.test_getClientIPDeprecatedc                 C   s.   t g }tddd}||_| d|  dS )z
        L{DummyRequest.getClientIP} supports IPv6 addresses, just like
        L{twisted.web.http.Request.getClientIP}.
        r    z::190  N)r   r   rY   r   rx   )r%   r<   rY   r   r   r   test_getClientIPSupportsIPv6  s    z.DummyRequestTests.test_getClientIPSupportsIPv6c                 C   s    t g }| }tt| dS )zu
        L{DummyRequest.getClientAddress} returns an L{IAddress}
        provider no C{client} has been set.
        N)r   ry   r   ZverifyObjectr   )r%   r<   Znullr   r   r   "test_getClientAddressWithoutClient  s    z4DummyRequestTests.test_getClientAddressWithoutClientc                 C   s2   t g }tddd}||_| }| || dS )zI
        L{DummyRequest.getClientAddress} returns the C{client}.
        r    r{   r   N)r   r   rY   ry   ZassertIs)r%   r<   rY   Zaddressr   r   r   test_getClientAddress  s
    z'DummyRequestTests.test_getClientAddressN)r   r   r   r   r   r   r   r   r   r   r   r   r     s
   
r   N)+r   Z
__future__r   r   __all__ior   Zzope.interfacer   r   Ztwisted.python.compatr	   Ztwisted.python.deprecater
   Zincrementalr   Ztwisted.internet.deferr   Ztwisted.internet.addressr   r   Ztwisted.internet.interfacesr   r   Ztwisted.trialr   Ztwisted.web.http_headersr   Ztwisted.web.resourcer   Ztwisted.web.serverr   r   r   Ztwisted.web._responsesr   objectr   r   r   rx   ZSynchronousTestCaser   r   r   r   r   <module>   s8   b  