o
    b;                     @   s:  d Z ddgZddl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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+Z,dS )z2
Helpers related to HTTP requests, used by tests.
DummyChannelDummyRequest    )BytesIO)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 )Foobar ).0lwr   r   @/usr/lib/python3/dist-packages/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.TCPP   FNc                 C   s,   |d u r
t ddd}|| _t | _g | _d S )NTCPz192.168.1.1i80  )r	   _peerr   written	producersselfpeerr   r   r   __init__2   s
   
zDummyChannel.TCP.__init__c                 C      | j S N)r*   r.   r   r   r   getPeer9   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   r8   <   s   
zDummyChannel.TCP.writec                 C   s   |D ]}|  | qd S r2   )r8   )r.   iovecr:   r   r   r   writeSequenceA   s   zDummyChannel.TCP.writeSequencec                 C   s   t dd| jS )Nr)   z10.0.0.1)r	   portr3   r   r   r   getHostE      zDummyChannel.TCP.getHostc                 C   s   | j ||f d S r2   )r,   appendr.   producer	streamingr   r   r   registerProducerH   s   z!DummyChannel.TCP.registerProducerc                 C      d S r2   r   r3   r   r   r   unregisterProducerK      z#DummyChannel.TCP.unregisterProducerc                 C   
   d| _ d S )NT)disconnectedr3   r   r   r   loseConnectionN      
zDummyChannel.TCP.loseConnectionr2   )r$   r%   r&   r=   rI   r0   r4   r8   r<   r>   rD   rF   rJ   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   rE   r2   r   r3   r   r   r   abortConnectionS      z DummyChannel.SSL.abortConnectionc                 C   rE   r2   r   r3   r   r   r   getTcpKeepAliveW   rM   z DummyChannel.SSL.getTcpKeepAlivec                 C   rE   r2   r   r3   r   r   r   getTcpNoDelay[   rM   zDummyChannel.SSL.getTcpNoDelayc                 C   rE   r2   r   r3   r   r   r   loseWriteConnection_   rM   z$DummyChannel.SSL.loseWriteConnectionc                 C   rE   r2   r   r.   enabledr   r   r   setTcpKeepAlivec   rM   z DummyChannel.SSL.setTcpKeepAlivec                 C   rE   r2   r   rQ   r   r   r   setTcpNoDelayg   rM   zDummyChannel.SSL.setTcpNoDelayc                 C   rE   r2   r   r3   r   r   r   getPeerCertificatek   rM   z#DummyChannel.SSL.getPeerCertificateN)
r$   r%   r&   rL   rN   rO   rP   rS   rT   rU   r   r   r   r   SSLQ   s    rV   Nc                 C   s   |  || _d S r2   )r)   	transportr-   r   r   r   r0   q      zDummyChannel.__init__c                 C   rE   r2   r   )r.   requestr   r   r   requestDonet   rG   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   )r   namevaluer   r   r   	<genexpr>z   s   " z,DummyChannel.writeHeaders.<locals>.<genexpr>)extendr@   rW   r<   )r.   versioncodereasonheadersresponse_lineheaderSequencer   r   r   writeHeadersw   s
   
zDummyChannel.writeHeadersc                 C   
   | j  S r2   )rW   r4   r3   r   r   r   r4   ~   rK   zDummyChannel.getPeerc                 C   rh   r2   )rW   r>   r3   r   r   r   r>      rK   zDummyChannel.getHostc                 C   s   | j || d S r2   )rW   rD   rA   r   r   r   rD      s   zDummyChannel.registerProducerc                 C      | j   d S r2   )rW   rF   r3   r   r   r   rF      r?   zDummyChannel.unregisterProducerc                 C      | j | d S r2   )rW   r8   r9   r   r   r   r8      rX   zDummyChannel.writec                 C   rj   r2   )rW   r<   )r.   r;   r   r   r   r<      rX   zDummyChannel.writeSequencec                 C   ri   r2   )rW   rJ   r3   r   r   r   rJ      r?   zDummyChannel.loseConnectionc                 C   rE   r2   r   r3   r   r   r   
endRequest   rG   zDummyChannel.endRequestc                 C   s   t | j| jS r2   )r5   rW   rV   r3   r   r   r   isSecure   r?   zDummyChannel.isSecurec                 C   rE   r2   r   r3   r   r   r   rL      rM   zDummyChannel.abortConnectionc                 C   rE   r2   r   r3   r   r   r   rN      rM   zDummyChannel.getTcpKeepAlivec                 C   rE   r2   r   r3   r   r   r   rO      rM   zDummyChannel.getTcpNoDelayc                 C   rE   r2   r   r3   r   r   r   rP      rM   z DummyChannel.loseWriteConnectionc                 C   rE   r2   r   r3   r   r   r   rS      rM   zDummyChannel.setTcpKeepAlivec                 C   rE   r2   r   r3   r   r   r   rT      rM   zDummyChannel.setTcpNoDelayc                 C   rE   r2   r   r3   r   r   r   rU      rM   zDummyChannel.getPeerCertificater2   )r$   r%   r&   r)   r   r   rV   r   r   siter0   rZ   rg   r4   r>   rD   rF   r8   r<   rJ   rk   rl   rL   rN   rO   rP   rS   rT   rU   r   r   r   r   r   -   s0    #

c                   @   s  e Zd ZU dZdZdZdZee e	d< dd Z
dd	 Zd9d
dZdd Zdd Zdd Zd:ddZdd Zdd Zded fddZdd Zdd Zdd  Zd:d!d"Zd#d$ Zd%d& Zeed'd(d)d*d+d,d-d. Zd/d0 Zd1d2 Zd3d4 Z d;d5d6Z!d7d8 Z"dS )<r   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   GETNclientc                 C   s"   d| _ | j r|  | j sdS 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)goresumeProducing)r.   prodsr   r   r   rD      s   zDummyRequest.registerProducerc                 C   rH   )Nr   )rp   r3   r   r   r   rF      rK   zDummyRequest.unregisterProducerc                 C   sl   g | _ g | _d| _|| _g | _d | _|ptd dt d| _i | _	t
 | _t
 | _d | _g | _d| _d| _d S )Nr      0)rm   uidreactors   dummys   HTTP/1.0)sitepathr+   finishedpostpathprepathsessionr   r   protoSessionargsr   requestHeadersresponseHeadersresponseCode_finishedDeferreds_serverNameclientproto)r.   ry   r{   rn   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}.
        )r~   getAllRawHeaderslower)r.   rd   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   )r~   getRawHeadersr   )r.   r]   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)r   addRawHeaderr.   r]   r^   r   r   r   	setHeader  s   zDummyRequest.setHeaderc                 C   s(   | j r| j S | jrJ d| j| _ | j S )Nz8Session cannot be requested after data has been written.)r{   r+   r|   )r.   sessionInterfacer   r   r   
getSession  s   zDummyRequest.getSessionc                 C   s,   | | }|tu 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   r8   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)r5   r6   r7   r+   r@   r9   r   r   r   r8   1  s   
zDummyRequest.writereturnc                 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   r   r@   )r.   rx   r   r   r   notifyFinish6  s   zDummyRequest.notifyFinishc                 C   s>   | j d | _ | jdur| j}d| _|D ]	}|d qdS dS )z}
        Record that the request is finished and callback and L{Deferred}s
        waiting for notification of this.
        ro   N)rx   r   callback)r.   	observersobsr   r   r   r   @  s   
zDummyRequest.finishc                 C   s2   | j dur| j }d| _ |D ]	}|| qdS dS )zK
        Errback and L{Deferreds} waiting for finish notification.
        N)r   errback)r.   rc   r   r   r   r   r   processingFailedL  s   
zDummyRequest.processingFailedc                 C   s   |g| j |< d S r2   )r}   r   r   r   r   addArgV  rX   zDummyRequest.addArgc                 C   s,   | j rJ 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+   formatjoinr   responseMessage)r.   rb   messager   r   r   setResponseCodeY  s   

zDummyRequest.setResponseCodec                 C       | j rJ dd| j d S )Nz<Last-Modified cannot be set after data has been written: {}.r   r+   r   r   )r.   whenr   r   r   setLastModifiedf     
zDummyRequest.setLastModifiedc                 C   r   )Nz3ETag cannot be set after data has been written: {}.r   r   )r.   tagr   r   r   setETagm  r   zDummyRequest.setETag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)r5   rn   r	   r
   hostr3   r   r   r   getClientIPt  s   zDummyRequest.getClientIPc                 C   s   | j du 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)rn   r#   r3   r   r   r   r   ~  s   
zDummyRequest.getClientAddressc                 C   r1   )z
        Get a dummy hostname associated to the HTTP request.

        @rtype: C{bytes}
        @returns: a dummy hostname
        )r   r3   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	   r3   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)	_forceSSLrl   r~   r   )r.   r   r=   ssldefault
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)NNr2   )r   )#r$   r%   r&   r'   urimethodrn   r   r   __annotations__rD   rF   r0   r   r   r   r   r   r8   r   r   r   r   r   r   r   r   r   r   r   r   r   r>   r   r   r   r   r   r   r      s8   
 

	



		
	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}
        )offendingFunctionsro   categoryr   z}twisted.web.test.requesthelper.DummyRequest.getClientIP was deprecated in Twisted 18.4.0; please use getClientAddress insteadN)r   r   flushWarningstest_getClientIPDeprecatedassertEquallengetDeprecationWarning)r.   rY   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::190  N)r   r
   rn   r   r   )r.   rY   rn   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   verifyObjectr   )r.   rY   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	   rn   r   assertIs)r.   rY   rn   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'   __all__ior   typingr   zope.interfacer   r   incrementalr   twisted.internet.addressr	   r
   twisted.internet.deferr   twisted.internet.interfacesr   r   twisted.internet.taskr   twisted.python.deprecater   twisted.trialr   twisted.web._responsesr   twisted.web.http_headersr   twisted.web.resourcer   twisted.web.serverr   r   r   textLinearWhitespaceComponentssanitizedTextbytesLinearWhitespaceComponentsr!   sanitizedBytesr#   r   r   SynchronousTestCaser   r   r   r   r   <module>   s<   
 
  