U
    n5{iç<  ã                   @  sN  d Z ddlmZ ddgZddlmZ ddlmZmZm	Z	 ddl
mZmZ ddlmZ dd	lmZm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  ddl!m"Z" ddl#m$Z$m%Z%m&Z& dd„ dD ƒZ'dZ(dd„ e'D ƒZ)e( *d¡Z+eeƒG dd„ dƒƒZ,G dd„ dƒZ-G dd„ dƒZ.G dd„ dej/ƒZ0dS ) z2
Helpers related to HTTP requests, used by tests.
é    )ÚannotationsÚDummyChannelÚDummyRequest)ÚBytesIO)ÚDictÚListÚOptional)ÚimplementerÚverify)ÚVersion)ÚIPv4AddressÚIPv6Address)ÚDeferred)ÚIAddressÚISSLTransport)ÚClock)Ú
deprecated)Úunittest)ÚFOUND)ÚHeaders)ÚResource)ÚNOT_DONE_YETÚSessionÚSitec                 C  s   g | ]}d |› d�‘qS )ZFooÚbar© )Ú.0Zlwr   r   úB/tmp/pip-unpacked-wheel-mnhg7r0q/twisted/web/test/requesthelper.pyÚ
<listcomp>   s     r   )úÚ
z
zFoo barc                 C  s   g | ]}|  d ¡‘qS )Úascii)Úencode)r   Ú	componentr   r   r   r   !   s    r!   c                   @  s   e Zd ZdZdS )ÚNullAddressz/
    A null implementation of L{IAddress}.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r$   '   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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.TCPéP   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__3   s
    zDummyChannel.TCP.__init__c                 C  s   | j S ©N)r+   ©r/   r   r   r   ÚgetPeer:   s    zDummyChannel.TCP.getPeerc                 C  s(   t |tƒstd|›�ƒ‚| j |¡ d S )Nz)Can only write bytes to a transport, not )Ú
isinstanceÚbytesÚ	TypeErrorr,   Úwrite©r/   Údatar   r   r   r7   =   s    
zDummyChannel.TCP.writec                 C  s   |D ]}|   |¡ qd S r1   )r7   )r/   Úiovecr9   r   r   r   ÚwriteSequenceB   s    zDummyChannel.TCP.writeSequencec                 C  s   t dd| jƒS )Nr*   z10.0.0.1)r   Úportr2   r   r   r   ÚgetHostF   s    zDummyChannel.TCP.getHostc                 C  s   | j  ||f¡ d S r1   )r-   Úappend©r/   ZproducerZ	streamingr   r   r   ÚregisterProducerI   s    z!DummyChannel.TCP.registerProducerc                 C  s   d S r1   r   r2   r   r   r   ÚunregisterProducerL   s    z#DummyChannel.TCP.unregisterProducerc                 C  s
   d| _ d S )NT)Údisconnectedr2   r   r   r   ÚloseConnectionO   s    zDummyChannel.TCP.loseConnection)N)r%   r&   r'   r<   rB   r0   r3   r7   r;   r=   r@   rA   rC   r   r   r   r   r*   /   s   
r*   c                   @  sD   e Z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.SSLc                 C  s   d S r1   r   r2   r   r   r   ÚabortConnectionT   s    z DummyChannel.SSL.abortConnectionc                 C  s   d S r1   r   r2   r   r   r   ÚgetTcpKeepAliveX   s    z DummyChannel.SSL.getTcpKeepAlivec                 C  s   d S r1   r   r2   r   r   r   ÚgetTcpNoDelay\   s    zDummyChannel.SSL.getTcpNoDelayc                 C  s   d S r1   r   r2   r   r   r   ÚloseWriteConnection`   s    z$DummyChannel.SSL.loseWriteConnectionc                 C  s   d S r1   r   ©r/   Zenabledr   r   r   ÚsetTcpKeepAlived   s    z DummyChannel.SSL.setTcpKeepAlivec                 C  s   d S r1   r   rH   r   r   r   ÚsetTcpNoDelayh   s    zDummyChannel.SSL.setTcpNoDelayc                 C  s   d S r1   r   r2   r   r   r   ÚgetPeerCertificatel   s    z#DummyChannel.SSL.getPeerCertificateN)
r%   r&   r'   rD   rE   rF   rG   rI   rJ   rK   r   r   r   r   ÚSSLR   s   rL   Nc                 C  s   |   |¡| _d S r1   )r*   Ú	transportr.   r   r   r   r0   r   s    zDummyChannel.__init__c                 C  s   d S r1   r   )r/   Úrequestr   r   r   ÚrequestDoneu   s    zDummyChannel.requestDonec                 C  sh   t |tƒrdd„ | ¡ D ƒ}|d | d | d }|g}| dd„ |D ƒ¡ | d¡ | j |¡ d S )Nc                 S  s"   g | ]\}}|D ]}||f‘qqS r   r   )r   ÚkÚvaluesÚvr   r   r   r   z   s      z-DummyChannel.writeHeaders.<locals>.<listcomp>ó    ó   
c                 s  s"   | ]\}}|d  | d V  qdS )s   : rT   Nr   )r   ÚnameÚvaluer   r   r   Ú	<genexpr>   s     z,DummyChannel.writeHeaders.<locals>.<genexpr>)r4   r   ÚgetAllRawHeadersÚextendr>   rM   r;   )r/   ÚversionÚcodeÚreasonÚheadersZresponse_lineZheaderSequencer   r   r   ÚwriteHeadersx   s    
ÿ
zDummyChannel.writeHeadersc                 C  s
   | j  ¡ S r1   )rM   r3   r2   r   r   r   r3   ƒ   s    zDummyChannel.getPeerc                 C  s
   | j  ¡ S r1   )rM   r=   r2   r   r   r   r=   †   s    zDummyChannel.getHostc                 C  s   | j  ||¡ d S r1   )rM   r@   r?   r   r   r   r@   ‰   s    zDummyChannel.registerProducerc                 C  s   | j  ¡  d S r1   )rM   rA   r2   r   r   r   rA   Œ   s    zDummyChannel.unregisterProducerc                 C  s   | j  |¡ d S r1   )rM   r7   r8   r   r   r   r7   �   s    zDummyChannel.writec                 C  s   | j  |¡ d S r1   )rM   r;   )r/   r:   r   r   r   r;   ’   s    zDummyChannel.writeSequencec                 C  s   | j  ¡  d S r1   )rM   rC   r2   r   r   r   rC   •   s    zDummyChannel.loseConnectionc                 C  s   d S r1   r   r2   r   r   r   Ú
endRequest˜   s    zDummyChannel.endRequestc                 C  s   t | j| jƒS r1   )r4   rM   rL   r2   r   r   r   ÚisSecure›   s    zDummyChannel.isSecurec                 C  s   d S r1   r   r2   r   r   r   rD   ž   s    zDummyChannel.abortConnectionc                 C  s   d S r1   r   r2   r   r   r   rE   ¢   s    zDummyChannel.getTcpKeepAlivec                 C  s   d S r1   r   r2   r   r   r   rF   ¦   s    zDummyChannel.getTcpNoDelayc                 C  s   d S r1   r   r2   r   r   r   rG   ª   s    z DummyChannel.loseWriteConnectionc                 C  s   d S r1   r   r2   r   r   r   rI   ®   s    zDummyChannel.setTcpKeepAlivec                 C  s   d S r1   r   r2   r   r   r   rJ   ²   s    zDummyChannel.setTcpNoDelayc                 C  s   d S r1   r   r2   r   r   r   rK   ¶   s    zDummyChannel.getPeerCertificate)N)r%   r&   r'   r*   r	   r   rL   r   r   Úsiter0   rO   r^   r3   r=   r@   rA   r7   r;   rC   r_   r`   rD   rE   rF   rG   rI   rJ   rK   r   r   r   r   r   .   s.   #

c                   @  s.  e Zd ZU dZdZdZdZded< ded< ded	< ded
< ded< ded< dd„ Zdd„ Z	dGdddddœdd„Z
dd„ Zdd„ Zdd„ ZdHdd „Zd!d"„ Zd#d$„ Zd%d&œd'd(„Zd)d*„ Zd+d,„ Zd-d.„ ZdId/d0„Zd1d2„ Zd3d4„ Zeed5d6d7d8ƒd9d:�d;d<„ ƒZd=d>„ Zd?d@„ ZdAdB„ ZdJdCdD„ZdEdF„ ZdS )Kr   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   GETNzOptional[IAddress]ÚclientzList[bytes]Úsitepathr,   ÚprepathzDict[bytes, List[bytes]]ÚargszList[Deferred[None]]Ú_finishedDeferredsc                 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/   ÚprodÚsr   r   r   r@   Ü   s    zDummyRequest.registerProducerc                 C  s
   d| _ d S )Nr   )rh   r2   r   r   r   rA   ë   s    zDummyRequest.unregisterProducerzlist[bytes]zOptional[Session]ÚNone)ÚpostpathÚsessionrb   Úreturnc                 C  sl   g | _ g | _d| _|| _g | _d | _|p6td dtƒ d�| _i | _	t
ƒ | _t
ƒ | _d | _g | _d| _d| _d S )Nr   ó   0)ra   ÚuidZreactors   dummys   HTTP/1.0)rc   r,   Úfinishedrl   rd   rm   r   r   ÚprotoSessionre   r   ÚrequestHeadersÚresponseHeadersÚresponseCoderf   Ú_serverNameZclientproto)r/   rl   rm   rb   r   r   r   r0   î   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}.
        éÿÿÿÿ)rs   rX   Úlower)r/   r]   rP   rR   r   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   )rs   ZgetRawHeadersrx   )r/   rU   r   r   r   Ú	getHeader  s    zDummyRequest.getHeaderc                 C  s   | j  ||¡ dS )zATODO: make this assert on write() if the header is content-lengthN)rt   ÚaddRawHeader©r/   rU   rV   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.)rm   r,   ÚAssertionErrorrr   )r/   ZsessionInterfacer   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   r7   Úfinish)r/   ÚresourceÚresultr   r   r   r€   -  s
    

zDummyRequest.renderc                 C  s"   t |tƒstdƒ‚| j |¡ d S )Nzwrite() only accepts bytes)r4   r5   r6   r,   r>   r8   r   r   r   r7   @  s    
zDummyRequest.writezDeferred[None])rn   c                 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   rf   r>   )r/   rq   r   r   r   ÚnotifyFinishE  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.
        rg   N)rq   rf   Úcallback)r/   Ú	observersÚobsr   r   r   r�   O  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)rf   Zerrback)r/   r\   r†   r‡   r   r   r   ÚprocessingFailed[  s
    
zDummyRequest.processingFailedc                 C  s   |g| j |< d S r1   )re   r|   r   r   r   ÚaddArge  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 hasbeen written: {}.ú@@@@N)r,   r~   ÚformatÚjoinru   ZresponseMessage)r/   r[   Úmessager   r   r   ÚsetResponseCodeh  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: {}.rŠ   ©r,   r~   r‹   rŒ   )r/   Úwhenr   r   r   ÚsetLastModifiedu  s    ÿ
ÿþzDummyRequest.setLastModifiedc                 C  s    | j rtd d | j ¡¡ƒ‚d S )Nz3ETag cannot be set after data has been written: {}.rŠ   r�   )r/   Útagr   r   r   ÚsetETag|  s    ÿ
ÿþzDummyRequest.setETagZTwistedé   é   r   ÚgetClientAddress)Úreplacementc                 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)r4   rb   r   r   Úhostr2   r   r   r   ÚgetClientIPƒ  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)rb   r$   r2   r   r   r   r–   �  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
        )rv   r2   r   r   r   ÚgetRequestHostname˜  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   r2   r   r   r   r=   ¡  s    zDummyRequest.getHostc                 C  sD   || _ |  ¡ rd}nd}||kr&|}nd||f }| 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   %b:%ds   hostN)Z	_forceSSLr`   rs   r{   )r/   r˜   r<   ÚsslÚdefaultZ
hostHeaderr   r   r   ÚsetHostª  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)rŽ   r   r}   )r/   Úurlr   r   r   ÚredirectÀ  s    
zDummyRequest.redirect)NN)N)N)r   ) r%   r&   r'   r(   ÚuriÚmethodrb   Ú__annotations__r@   rA   r0   ry   rz   r}   r   r€   r7   r„   r�   rˆ   r‰   rŽ   r‘   r“   r   r   r™   r–   rš   r=   rž   r    r   r   r   r   r   »   sD   
  ü
	



			
c                   @  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offendingFunctionsrg   Úcategoryr�   z}twisted.web.test.requesthelper.DummyRequest.getClientIP was deprecated in Twisted 18.4.0; please use getClientAddress insteadN)r   r™   ZflushWarningsÚtest_getClientIPDeprecatedÚassertEqualÚlenÚgetÚDeprecationWarning)r/   rN   ÚwarningsÚ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::1é90  N)r   r   rb   r§   r™   )r/   rN   rb   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   r–   r
   ZverifyObjectr   )r/   rN   Ú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   rb   r–   ZassertIs)r/   rN   rb   Ú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)1r(   Ú
__future__r   Ú__all__Úior   Útypingr   r   r   Zzope.interfacer	   r
   Úincrementalr   Ztwisted.internet.addressr   r   Ztwisted.internet.deferr   Ztwisted.internet.interfacesr   r   Ztwisted.internet.taskr   Ztwisted.python.deprecater   Ztwisted.trialr   Ztwisted.web._responsesr   Ztwisted.web.http_headersr   Ztwisted.web.resourcer   Ztwisted.web.serverr   r   r   ZtextLinearWhitespaceComponentsZsanitizedTextZbytesLinearWhitespaceComponentsr"   ZsanitizedBytesr$   r   r   ZSynchronousTestCaser¤   r   r   r   r   Ú<module>   s<   ÿ
   