o
    ¯bÌU  ã                   @   sð   d 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 dd	lmZ dd
lmZ ddlmZ eeu rKdd„ Zdd„ Zndd„ Zdd„ ZG dd„ dƒZG dd„ dƒZG dd„ dƒZeeƒG dd„ dƒƒZdgZdS )zo
An implementation of
U{Python Web Server Gateway Interface v1.0.1<http://www.python.org/dev/peps/pep-3333/>}.
é    )ÚSequence)Úexc_info)Úwarn)Úimplementer)ÚblockingCallFromThread)ÚLogger)ÚFailure)ÚINTERNAL_SERVER_ERROR)Ú	IResource)ÚNOT_DONE_YETc                 C   s   t | tƒr| S |  d¡S )zü
        Convert C{string} to an ISO-8859-1 byte string, if it is not already.

        @type string: C{str}/C{bytes} or C{unicode}
        @rtype: C{str}/C{bytes}

        @raise UnicodeEncodeError: If C{string} contains non-ISO-8859-1 chars.
        ú
iso-8859-1)Ú
isinstanceÚstrÚencode©Ústring© r   ú2/usr/lib/python3/dist-packages/twisted/web/wsgi.pyÚ_wsgiString*   s   
	
r   c                 C   s   | S )zœ
        Return C{string} as is; a WSGI string is a byte string in Python 2.

        @type string: C{str}/C{bytes}
        @rtype: C{str}/C{bytes}
        r   r   r   r   r   Ú_wsgiStringToBytes8   s   r   c                 C   s$   t | tƒr|  d¡ d¡S |  d¡S )as  
        Convert C{string} to a WSGI "bytes-as-unicode" string.

        If it's a byte string, decode as ISO-8859-1. If it's a Unicode string,
        round-trip it to bytes and back using ISO-8859-1 as the encoding.

        @type string: C{str} or C{bytes}
        @rtype: C{str}

        @raise UnicodeEncodeError: If C{string} contains non-ISO-8859-1 chars.
        r   )r   r   r   Údecoder   r   r   r   r   D   s   

c                 C   s
   |   d¡S )zö
        Convert C{string} from a WSGI "bytes-as-unicode" string to an
        ISO-8859-1 byte string.

        @type string: C{str}
        @rtype: C{bytes}

        @raise UnicodeEncodeError: If C{string} contains non-ISO-8859-1 chars.
        r   )r   r   r   r   r   r   U   s   

c                   @   s.   e Zd ZdZeƒ Zdd„ Zdd„ Zdd„ ZdS )	Ú_ErrorStreama·  
    File-like object instances of which are used as the value for the
    C{'wsgi.errors'} key in the C{environ} dictionary passed to the application
    object.

    This simply passes writes on to L{logging<twisted.logger>} system as
    error events from the C{'wsgi'} system.  In the future, it may be desirable
    to expose more information in the events it logs, such as the application
    object which generated the message.
    c                 C   s^   t |tƒs"ttu rtd|t|ƒjf td� ntd|t|ƒjf ƒ‚| jj	|dd|fd� dS )aG  
        Generate an event for the logging system with the given bytes as the
        message.

        This is called in a WSGI application thread, not the I/O thread.

        @type data: str

        @raise TypeError: On Python 3, if C{data} is not a native string. On
            Python 2 a warning will be issued.
        z+write() argument should be str, not %r (%s)©Úcategoryz)write() argument must be str, not %r (%s)ÚwsgiT)ÚsystemÚisErrorÚmessageN)
r   r   Úbytesr   ÚtypeÚ__name__ÚUnicodeWarningÚ	TypeErrorÚ_logÚerror)ÚselfÚdatar   r   r   Úwritep   s   
ÿýÿÿz_ErrorStream.writec                 C   s   |   d |¡¡ dS )a™  
        Join the given lines and pass them to C{write} to be handled in the
        usual way.

        This is called in a WSGI application thread, not the I/O thread.

        @param iovec: A C{list} of C{'\n'}-terminated C{str} which will be
            logged.

        @raise TypeError: On Python 3, if C{iovec} contains any non-native
            strings. On Python 2 a warning will be issued.
        Ú N)r'   Újoin)r%   Úiovecr   r   r   Ú
writelines�   s   z_ErrorStream.writelinesc                 C   s   dS )zÈ
        Nothing is buffered, so flushing does nothing.  This method is required
        to exist by PEP 333, though.

        This is called in a WSGI application thread, not the I/O thread.
        Nr   ©r%   r   r   r   Úflushœ   s    z_ErrorStream.flushN)	r    Ú
__module__Ú__qualname__Ú__doc__r   r#   r'   r+   r-   r   r   r   r   r   b   s    r   c                   @   s>   e Zd ZdZdd„ Zddd„Zddd„Zdd	d
„Zdd„ ZdS )Ú_InputStreamaˆ  
    File-like object instances of which are used as the value for the
    C{'wsgi.input'} key in the C{environ} dictionary passed to the application
    object.

    This only exists to make the handling of C{readline(-1)} consistent across
    different possible underlying file-like object implementations.  The other
    supported methods pass through directly to the wrapped object.
    c                 C   s
   || _ dS )zt
        Initialize the instance.

        This is called in the I/O thread, not a WSGI application thread.
        N)Ú_wrapped)r%   Úinputr   r   r   Ú__init__°   ó   
z_InputStream.__init__Nc                 C   ó   |du r	| j  ¡ S | j  |¡S )zƒ
        Pass through to the underlying C{read}.

        This is called in a WSGI application thread, not the I/O thread.
        N)r2   Úread©r%   Úsizer   r   r   r7   ¸   ó   
z_InputStream.readc                 C   s&   |dks|du r| j  ¡ S | j  |¡S )zÅ
        Pass through to the underlying C{readline}, with a size of C{-1} replaced
        with a size of L{None}.

        This is called in a WSGI application thread, not the I/O thread.
        éÿÿÿÿN)r2   Úreadliner8   r   r   r   r<   Ã   s   	
z_InputStream.readlinec                 C   r6   )zˆ
        Pass through to the underlying C{readlines}.

        This is called in a WSGI application thread, not the I/O thread.
        N)r2   Ú	readlinesr8   r   r   r   r=   Ð   r:   z_InputStream.readlinesc                 C   s
   t | jƒS )z‡
        Pass through to the underlying C{__iter__}.

        This is called in a WSGI application thread, not the I/O thread.
        )Úiterr2   r,   r   r   r   Ú__iter__Û   r5   z_InputStream.__iter__©N)	r    r.   r/   r0   r4   r7   r<   r=   r?   r   r   r   r   r1   ¥   s    



r1   c                   @   sT   e Zd ZdZdZeƒ Zdd„ Zdd„ Zddd	„Z	d
d„ Z
dd„ Zdd„ Zdd„ ZdS )Ú_WSGIResponsea$  
    Helper for L{WSGIResource} which drives the WSGI application using a
    threadpool and hooks it up to the L{http.Request}.

    @ivar started: A L{bool} indicating whether or not the response status and
        headers have been written to the request yet.  This may only be read or
        written in the WSGI application thread.

    @ivar reactor: An L{IReactorThreads} provider which is used to call methods
        on the request in the I/O thread.

    @ivar threadpool: A L{ThreadPool} which is used to call the WSGI
        application object in a non-I/O thread.

    @ivar application: The WSGI application object.

    @ivar request: The L{http.Request} upon which the WSGI environment is
        based and to which the application's output will be sent.

    @ivar environ: The WSGI environment L{dict}.

    @ivar status: The HTTP response status L{str} supplied to the WSGI
        I{start_response} callable by the application.

    @ivar headers: A list of HTTP response headers supplied to the WSGI
        I{start_response} callable by the application.

    @ivar _requestFinished: A flag which indicates whether it is possible to
        generate more response data or not.  This is L{False} until
        L{http.Request.notifyFinish} tells us the request is done,
        then L{True}.
    Fc                 C   sŠ  d| _ || _|| _|| _|| _| j ¡  | j¡ |jr$dd 	|j¡ }nd}|j
r2dd 	|j
¡ }nd}|j dd¡}t|ƒdkrDd}n|d }t|jƒt| ¡ jƒt|ƒt|ƒt|ƒt| d¡pbdƒt| d¡pjdƒt| ¡ ƒtt| ¡ jƒƒt|jƒd	œ
| _d | j_|j ¡ D ]!\}	}
d
t|	ƒ ¡  dd¡ }	d 	dd„ |
D ƒ¡ dd¡| j|	< q‰| j d| ¡ rµdp¶ddddt ƒ t!|j"ƒdœ¡ d S )NFó   /ó    ó   ?é   s   content-typer(   s   content-length)
ÚREQUEST_METHODÚREMOTE_ADDRÚSCRIPT_NAMEÚ	PATH_INFOÚQUERY_STRINGÚCONTENT_TYPEÚCONTENT_LENGTHÚSERVER_NAMEÚSERVER_PORTÚSERVER_PROTOCOLÚHTTP_ú-Ú_ú,c                 s   s   � | ]}t |ƒV  qd S r@   )r   )Ú.0Úvr   r   r   Ú	<genexpr>9  s   € z)_WSGIResponse.__init__.<locals>.<genexpr>Ú
ú )rE   r   ÚhttpsÚhttpT)zwsgi.versionzwsgi.url_schemezwsgi.run_oncezwsgi.multithreadzwsgi.multiprocesszwsgi.errorsz
wsgi.input)#ÚstartedÚreactorÚ
threadpoolÚapplicationÚrequestÚnotifyFinishÚaddBothÚ	_finishedÚprepathr)   ÚpostpathÚuriÚsplitÚlenr   ÚmethodÚgetClientAddressÚhostÚ	getHeaderÚgetRequestHostnamer   ÚgetHostÚportÚclientprotoÚenvironÚdefaultContentTypeÚrequestHeadersÚgetAllRawHeadersÚupperÚreplaceÚupdateÚisSecurer   r1   Úcontent)r%   r\   r]   r^   r_   Ú
scriptNameÚpathInfoÚpartsÚqueryStringÚnameÚvaluesr   r   r   r4   	  sV   
öÿëÿz_WSGIResponse.__init__c                 C   s
   d| _ dS )zc
        Record the end of the response generation for the request being
        serviced.
        TN)Ú_requestFinished)r%   Úignoredr   r   r   rb   W  s   
z_WSGIResponse._finishedNc                 C   s(  | j r|dur|d  |d ¡‚t|tƒs td |t|ƒj¡ƒ‚t|tƒr&nt|t	ƒr9t
d|t|ƒjf td� ntd|t|ƒjf ƒ‚|D ]D}t|tƒrNnt|t	ƒrat
d|t|ƒjf td� ntd	|t|ƒjf ƒ‚t|ƒdkrytd
|›�ƒ‚|D ]}t|tƒs‰td|›�ƒ‚q{qF|| _|| _| jS )z¼
        The WSGI I{start_response} callable.  The given values are saved until
        they are needed to generate the response.

        This will be called in a non-I/O thread.
        NrE   é   z!status must be str, not {!r} ({})z%headers should be a list, not %r (%s)r   z#headers must be a list, not %r (%s)z0header should be a (str, str) tuple, not %r (%s)z.header must be a (str, str) tuple, not %r (%s)z'header must be a (str, str) tuple, not z%header must be (str, str) tuple, not )r[   Úwith_tracebackr   r   r"   Úformatr   r    Úlistr   r   ÚRuntimeWarningÚtuplerg   ÚstatusÚheadersr'   )r%   r‡   rˆ   ÚexcInfoÚheaderÚelemr   r   r   ÚstartResponse^  s^   

ÿÿ
	
ÿýÿÿ

ÿýÿÿ
ÿÿz_WSGIResponse.startResponsec                    s0   ‡ ‡fdd„}zt ˆj|ˆjƒW dˆ_S dˆ_w )a   
        The WSGI I{write} callable returned by the I{start_response} callable.
        The given bytes will be written to the response body, possibly flushing
        the status and headers first.

        This will be called in a non-I/O thread.
        c                    s   | sˆ  ¡  ˆj ˆ ¡ d S r@   )Ú_sendResponseHeadersr_   r'   ©r[   ©r&   r%   r   r   Ú	wsgiWriteÅ  s   z&_WSGIResponse.write.<locals>.wsgiWriteT)r   r\   r[   )r%   r&   r�   r   r�   r   r'   ¤  s   !z_WSGIResponse.writec                 C   sd   | j  dd¡\}}t|ƒ}| j |t|ƒ¡ | jD ]\}}| ¡ dvr/| jj 	t|ƒt|ƒ¡ qdS )a,  
        Set the response code and response headers on the request object, but
        do not flush them.  The caller is responsible for doing a write in
        order for anything to actually be written out in response to the
        request.

        This must be called in the I/O thread.
        NrE   )ÚserverÚdate)
r‡   rf   Úintr_   ÚsetResponseCoder   rˆ   ÚlowerÚresponseHeadersÚaddRawHeader)r%   Úcoder   r}   Úvaluer   r   r   r�   Ï  s   	ÿ€ýz"_WSGIResponse._sendResponseHeadersc                 C   s   | j  | j¡ dS )zo
        Start the WSGI application in the threadpool.

        This must be called in the I/O thread.
        N)r]   ÚcallInThreadÚrunr,   r   r   r   Ústartã  s   z_WSGIResponse.startc                    s°   z(ˆ   ˆ jˆ j¡}|D ]}|rˆ  |¡ ˆ jr nqt|ddƒ}|dur'|ƒ  W n tyD   ‡ fdd„}ˆ jj|ˆ j	gt
ƒ ¢R Ž  Y nw ‡ fdd„}ˆ j |ˆ j	¡ dˆ _	dS )z°
        Call the WSGI application object, iterate it, and handle its output.

        This must be called in a non-I/O thread (ie, a WSGI application
        thread).
        ÚcloseNc                    sD   ˆ j jdt|||ƒd� | rˆ j ¡  d S ˆ j t¡ ˆ j ¡  d S )NzWSGI application error)Úfailure)r#   rž   r   r_   ÚloseConnectionr”   r	   Úfinish)r[   r   r™   Ú	tracebackr,   r   r   Ú	wsgiErrorþ  s   ÿz$_WSGIResponse.run.<locals>.wsgiErrorc                    s$   ˆ j s| s	ˆ  ¡  ˆ j ¡  d S d S r@   )r   r�   r_   r    rŽ   r,   r   r   Ú
wsgiFinish  s
   ýz%_WSGIResponse.run.<locals>.wsgiFinishT)r^   rp   rŒ   r'   r   ÚgetattrÚBaseExceptionr\   ÚcallFromThreadr[   r   )r%   ÚappIteratorr‹   r�   r¢   r£   r   r,   r   r›   ë  s&   
ÿ€
ô
z_WSGIResponse.runr@   )r    r.   r/   r0   r   r   r#   r4   rb   rŒ   r'   r�   rœ   r›   r   r   r   r   rA   ä   s    !N
F+rA   c                   @   s4   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚWSGIResourceaÕ  
    An L{IResource} implementation which delegates responsibility for all
    resources hierarchically inferior to it to a WSGI application.

    @ivar _reactor: An L{IReactorThreads} provider which will be passed on to
        L{_WSGIResponse} to schedule calls in the I/O thread.

    @ivar _threadpool: A L{ThreadPool} which will be passed on to
        L{_WSGIResponse} to run the WSGI application object.

    @ivar _application: The WSGI application object.
    Tc                 C   s   || _ || _|| _d S r@   )Ú_reactorÚ_threadpoolÚ_application)r%   r\   r]   r^   r   r   r   r4   (  s   
zWSGIResource.__init__c                 C   s    t | j| j| j|ƒ}| ¡  tS )a¾  
        Turn the request into the appropriate C{environ} C{dict} suitable to be
        passed to the WSGI application object and then pass it on.

        The WSGI application object is given almost complete control of the
        rendering process.  C{NOT_DONE_YET} will always be returned in order
        and response completion will be dictated by the application object, as
        will the status, headers, and the response body.
        )rA   r©   rª   r«   rœ   r   )r%   r_   Úresponser   r   r   Úrender-  s
   
ÿzWSGIResource.renderc                 C   ó   t dƒ‚)z»
        Reject attempts to retrieve a child resource.  All path segments beyond
        the one which refers to this resource are handled by the WSGI
        application object.
        z/Cannot get IResource children from WSGIResource©ÚRuntimeError)r%   r}   r_   r   r   r   ÚgetChildWithDefault=  ó   z WSGIResource.getChildWithDefaultc                 C   r®   )zÖ
        Reject attempts to add a child resource to this resource.  The WSGI
        application object handles all path segments beneath this resource, so
        L{IResource} children can never be found.
        z0Cannot put IResource children under WSGIResourcer¯   )r%   ÚpathÚchildr   r   r   ÚputChildE  r²   zWSGIResource.putChildN)	r    r.   r/   r0   ÚisLeafr4   r­   r±   rµ   r   r   r   r   r¨     s    r¨   N)r0   Úcollections.abcr   Úsysr   Úwarningsr   Úzope.interfacer   Útwisted.internet.threadsr   Útwisted.loggerr   Útwisted.python.failurer   Útwisted.web.httpr	   Útwisted.web.resourcer
   Útwisted.web.serverr   r   r   r   r   r   r1   rA   r¨   Ú__all__r   r   r   r   Ú<module>   s0   
C?  3
8