Ë
    #ïàj78  ã                   ó*  — d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	  G d„ dej                  «      Z G d	„ d
ej                  «      Z G d„ de«      Z G d„ de«      Zej                  «       Z G d„ d«      Z e«       j'                  eeeee¬«       y)aÊ  This class holds Cheroot WSGI server implementation.

Simplest example on how to use this server::

    from cheroot import wsgi

    def my_crazy_app(environ, start_response):
        status = '200 OK'
        response_headers = [('Content-type','text/plain')]
        start_response(status, response_headers)
        return [b'Hello world!']

    addr = '0.0.0.0', 8070
    server = wsgi.Server(addr, my_crazy_app)
    server.start()

The Cheroot WSGI server can serve as many WSGI applications
as you want in one instance by using a PathInfoDispatcher::

    path_map = {
        '/': my_crazy_app,
        '/blog': my_blog_app,
    }
    d = wsgi.PathInfoDispatcher(path_map)
    server = wsgi.Server(addr, d)
é    Né   )Úserver)ÚbtonÚntob)Ú
threadpoolc                   ót   ‡ — e Zd ZdZdZ	 	 	 	 	 	 	 	 	 	 	 	 dˆ fd„	Zed„ «       Zej                  d„ «       Zˆ xZ	S )ÚServerz8A subclass of HTTPServer which calls a WSGI application.©r   r   c                 óØ   •— t         t        | �  |t        | j                     ||||¬«       || _        || _        || _        || _        t        j                  | |xs d||	|
¬«      | _        y)a‘  Initialize WSGI Server instance.

        Args:
            bind_addr (tuple): network interface to listen to
            wsgi_app (callable): WSGI application callable
            numthreads (int): number of threads for WSGI thread pool
            server_name (str): web server name to be advertised via
                Server HTTP header
            max (int): maximum number of worker threads
            request_queue_size (int): the 'backlog' arg to
                socket.listen(); max queued connections
            timeout (int): the timeout in seconds for accepted connections
            shutdown_timeout (int): the total time, in seconds, to
                wait for worker threads to cleanly exit
            accepted_queue_size (int): maximum number of active
                requests in queue
            accepted_queue_timeout (int): timeout for putting request
                into queue
        )ÚgatewayÚserver_nameÚpeercreds_enabledÚpeercreds_resolve_enabledÚ
reuse_portr   )ÚminÚmaxÚaccepted_queue_sizeÚaccepted_queue_timeoutN)Úsuperr	   Ú__init__Úwsgi_gatewaysÚwsgi_versionÚwsgi_appÚrequest_queue_sizeÚtimeoutÚshutdown_timeoutr   Ú
ThreadPoolÚrequests)ÚselfÚ	bind_addrr   Ú
numthreadsr   r   r   r   r   r   r   r   r   r   Ú	__class__s                 €ú;/srv/dav/.venv/lib/python3.12/site-packages/cheroot/wsgi.pyr   zServer.__init__*   s|   ø€ ôF 	Œf�dÑ$ØÜ! $×"3Ñ"3Ñ4Ø#Ø/Ø&?Ø!ð 	%ô 	
ð !ˆŒØ"4ˆÔØˆŒØ 0ˆÔÜ"×-Ñ-ØØ’˜aØØ 3Ø#9ô
ˆ�ó    c                 ó.   — | j                   j                  S )zSet minimum number of threads.©r   r   ©r   s    r#   r!   zServer.numthreadsa   s   € ð �}‰}× Ñ Ð r$   c                 ó&   — || j                   _        y ©Nr&   )r   Úvalues     r#   r!   zServer.numthreadsf   s   € à!ˆ�‰Õr$   )é
   Néÿÿÿÿé   r+   r-   r,   r+   FFF)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Úpropertyr!   ÚsetterÚ__classcell__©r"   s   @r#   r	   r	   $   se   ø„ ÙBà€LØ)ð ØØØØØØØ!ØØ"'Øõ5
ðn ñ!ó ð!ð ×Ññ"ó ô"r$   r	   c                   ó\   ‡ — e Zd ZdZˆ fd„Zed„ «       Zd„ Zd„ Zd	d„Z	e
d„ «       Zd„ Zˆ xZS )
ÚGatewayz/A base class to interface HTTPServer with WSGI.c                 ór   •— t         t        | �  |«       d| _        | j	                  «       | _        d| _        y)zzInitialize WSGI Gateway instance with request.

        Args:
            req (HTTPRequest): current HTTP request
        FN)r   r7   r   Ústarted_responseÚget_environÚenvÚremaining_bytes_out)r   Úreqr"   s     €r#   r   zGateway.__init__n   s4   ø€ ô 	Œg�tÑ% cÔ*Ø %ˆÔØ×#Ñ#Ó%ˆŒØ#'ˆÕ r$   c                 ó^   — | j                  «       D �ci c]  }|j                  |“Œ c}S c c}w )z³Create a mapping of gateways and their versions.

        Returns:
            dict[tuple[int,int],class]: map of gateway version and
                corresponding class

        )Ú__subclasses__Úversion)ÚclsÚgws     r#   Úgateway_mapzGateway.gateway_mapy   s)   € ð *-×);Ñ);Ó)=Ö> 2�—
‘
˜B‘Ò>Ð>ùÒ>s   “*c                 ó   — t         ‚)ú;Return a new environ dict targeting the given wsgi.version.)ÚNotImplementedErrorr'   s    r#   r:   zGateway.get_environ„   s   € ä!Ð!r$   c                 óÜ  — | j                   j                  j                  | j                  | j                  «      }	 t        d|«      D ].  }t        |t        «      st        d«      ‚| j                  |«       Œ0 	 | j                   j                  «        t        |d«      r|j                  «        yy# | j                   j                  «        t        |d«      r|j                  «        w w xY w)aº  Process the current request.

        From :pep:`333`:

            The start_response callable must not actually transmit
            the response headers. Instead, it must store them for the
            server or gateway to transmit only after the first
            iteration of the application return value that yields
            a NON-EMPTY string, or upon the application's first
            invocation of the write() callable.
        Nz"WSGI Applications must yield bytesÚclose)r=   r   r   r;   Ústart_responseÚfilterÚ
isinstanceÚbytesÚ
ValueErrorÚwriteÚensure_headers_sentÚhasattrrH   )r   ÚresponseÚchunks      r#   ÚrespondzGateway.respondˆ   s½   € ð —8‘8—?‘?×+Ñ+¨D¯H©H°d×6IÑ6IÓJˆð		!Ü  hÓ/ò "�Ü! %¬Ô/Ü$Ð%IÓJÐJØ—
‘
˜5Õ!ñ"ð �H‰H×(Ñ(Ô*Ü�x Ô)Ø—‘Õ ð *øð �H‰H×(Ñ(Ô*Ü�x Ô)Ø—‘Õ ð *ús   ¼=B2 Â29C+c                 ó  — | j                   r|st        d«      ‚d| _         | j                  j                  r|d   }|‚| j	                  |«      | j                  _        |D ]Ÿ  \  }}t        |t        «      st        d|z  «      ‚t        |t        «      st        d|z  «      ‚|j                  «       dk(  rt        |«      | _        t        |«      t        |«      f}| j                  j                  j                  |«       Œ¡ | j                  S )z)WSGI callable to begin the HTTP response.z:WSGI start_response called a second time with no exc_info.Tr   z/WSGI response header key %r is not of type str.z1WSGI response header value %r is not of type str.zcontent-length)r9   ÚRuntimeErrorr=   Úsent_headersÚ_encode_statusÚstatusrK   ÚstrÚ	TypeErrorÚlowerÚintr<   r   Ú
outheadersÚappendrN   )r   rX   ÚheadersÚexc_infor*   ÚkÚvÚ
out_headers           r#   rI   zGateway.start_response    s  € ð × Ò ©ÜØLóð ð !%ˆÔð
 �8‰8× Ò Ø˜Q‘KˆEØˆKà×-Ñ-¨fÓ5ˆ�‰Œàò 	3‰DˆAˆqÜ˜a¤Ô%ÜØEÈÑIóð ô ˜a¤Ô%ÜØGÈ!ÑKóð ð �w‰w‹yÐ,Ò,Ü+.¨q«6�Ô(Ü˜a›¤$ q£'Ð)ˆJØ�H‰H×Ñ×&Ñ& zÕ2ð	3ð �z‰zÐr$   c                 óZ   — t        | t        «      st        d«      ‚| j                  d«      S )a:  Cast status to bytes representation of current Python version.

        According to :pep:`3333`, when using Python 3, the response status
        and headers must be bytes masquerading as Unicode; that is, they
        must be of type "str" but are restricted to code points in the
        "Latin-1" set.
        z(WSGI response status is not of type str.ú
ISO-8859-1)rK   rY   rZ   Úencode)rX   s    r#   rW   zGateway._encode_statusÃ   s)   € ô ˜&¤#Ô&ÜÐFÓGÐGØ�}‰}˜\Ó*Ð*r$   c                 óx  — | j                   st        d«      ‚t        |«      }| j                  }|�=||kD  r8| j                  j
                  s| j                  j                  dd«       n|d| }| j                  j                  «        | j                  j                  |«       |�||z  }|dk  rt        d«      ‚yy)zÉWSGI callable to write unbuffered data to the client.

        This method is also used internally by start_response (to write
        data from the iterable returned by the WSGI application).
        z(WSGI write called before start_response.Nz500 Internal Server ErrorzLThe requested resource returned more bytes than the declared Content-Length.r   z2Response body exceeds the declared Content-Length.)
r9   rU   Úlenr<   r=   rV   Úsimple_responserO   rN   rM   )r   rR   ÚchunklenÚrbos       r#   rN   zGateway.writeÐ   s»   € ð ×$Ò$ÜÐIÓJÐJä�u“:ˆØ×&Ñ&ˆØˆ?˜x¨#š~Ø—8‘8×(Ò(à—‘×(Ñ(Ø/ð/õð ˜d˜s˜�à�‰×$Ñ$Ô&à�‰�‰�uÔàˆ?Ø�8‰OˆCØ�QŠwÜ ØHóð ð ð r$   r)   )r.   r/   r0   r1   r   ÚclassmethodrC   r:   rS   rI   ÚstaticmethodrW   rN   r4   r5   s   @r#   r7   r7   k   sH   ø„ Ù9ô	(ð ñ?ó ð?ò"ò!ó0!ðF ñ
+ó ð
+ö!r$   r7   c                   ó   — e Zd ZdZdZd„ Zy)Ú
Gateway_10z8A Gateway class to interface HTTPServer with WSGI 1.0.x.r
   c                 ó²  — | j                   }|j                  }i d|j                  j                  “dt	        |j
                  «      “dt	        |j                  «      “d|j                  xs d“dt        |j                  xs d«      “dt	        |j                  «      “dt	        |j                  «      “d	d“d
|j                  j                  “dt	        |j                  «      “d|j                  j                  “dt        j                   “d|j"                  “dt%        |j&                  «      “dd“dd“dd“t	        |j(                  «      | j*                  dœ¥}t-        |j                  j.                  t        «      r‡d|d<   	 t        |j0                  «      |d<   t        |j2                  «      |d<   t        |j4                  «      |d<   t        |j6                  «      |d<   t        |j8                  «      |d<   |d   |d<   n%t        |j                  j.                  d   «      |d<   |j=                  d„ |j>                  jA                  «       D «       «       |jC                  dd «      }|�||d!<   |jC                  d"d «      }|�||d#<   |j                  jD                  r%|j=                  |j                  jD                  «       |S # t:        $ r Y Œªw xY w)$rE   ÚACTUAL_SERVER_PROTOCOLÚ	PATH_INFOÚQUERY_STRINGÚREMOTE_ADDRÚ ÚREMOTE_PORTÚREQUEST_METHODÚREQUEST_URIÚSCRIPT_NAMEÚSERVER_NAMEÚSERVER_PROTOCOLÚSERVER_SOFTWAREzwsgi.errorsz
wsgi.inputzwsgi.input_terminatedzwsgi.multiprocessFzwsgi.multithreadTzwsgi.run_once)zwsgi.url_schemezwsgi.versionÚSERVER_PORTÚX_REMOTE_PIDÚX_REMOTE_UIDÚX_REMOTE_GIDÚX_REMOTE_USERÚX_REMOTE_GROUPÚREMOTE_USERr   c              3   óª   K  — | ]K  \  }}d j                  t        |«      j                  «       j                  dd«      ¬«      t        |«      f–— ŒM y­w)zHTTP_{header_name!s}ú-Ú_)Úheader_nameN)Úformatr   ÚupperÚreplace)Ú.0ra   rb   s      r#   ú	<genexpr>z)Gateway_10.get_environ.<locals>.<genexpr>.  sV   è ø€ ò 
ñ ��1ð '×-Ñ-Ü $ Q£§¡£× 7Ñ 7¸¸SÓ Að .ó ô �Q“ô	ñ
ùs   ‚AAÚHTTP_CONTENT_TYPENÚCONTENT_TYPEÚHTTP_CONTENT_LENGTHÚCONTENT_LENGTH)#r=   Úconnr   Úprotocolr   ÚpathÚqsÚremote_addrrY   Úremote_portÚmethodÚurir   Úrequest_protocolÚsoftwareÚsysÚstderrÚrfileÚboolÚchunked_readÚschemer@   rK   r    Úpeer_pidÚpeer_uidÚpeer_gidÚ	peer_userÚ
peer_grouprU   ÚupdateÚ	inheadersÚitemsÚpopÚssl_env)r   r=   Úreq_connr;   ÚctÚcls         r#   r:   zGateway_10.get_environù   sä  € à�h‰hˆØ—8‘8ˆð
ð % c§j¡j×&9Ñ&9ð	
ð
 œ˜cŸh™h›ð
ð œD §¡›Lð
ð ˜8×/Ñ/Ò5°2ð
ð œ3˜x×3Ñ3Ò9°rÓ:ð
ð œd 3§:¡:Ó.ð
ð œ4 §¡›=ð
ð ˜2ð
ð ˜3Ÿ:™:×1Ñ1ð
ð œt C×$8Ñ$8Ó9ð
ð ˜sŸz™z×2Ñ2ð
ð  œ3Ÿ:™:ð!
ð" ˜#Ÿ)™)ð#
ð$ $¤T¨#×*:Ñ*:Ó%;ð%
ð&   ð'
ð(  ð)
ð* ˜Uð+
ô,  $ C§J¡JÓ/Ø ŸL™Lò/
ˆô4 �c—j‘j×*Ñ*¬CÔ0ð "$ˆC�ÑðÜ&)¨(×*;Ñ*;Ó&<��NÑ#Ü&)¨(×*;Ñ*;Ó&<��NÑ#Ü&)¨(×*;Ñ*;Ó&<��NÑ#ä'*¨8×+=Ñ+=Ó'>��OÑ$Ü(+¨H×,?Ñ,?Ó(@�Ð$Ñ%à%(¨Ñ%9��MÒ"ô "% S§Z¡Z×%9Ñ%9¸!Ñ%<Ó!=ˆC�Ñð 	�
‰
ñ 
ð Ÿ™×+Ñ+Ó-ô
ô 	
ð �W‰WÐ(¨$Ó/ˆØˆ>Ø"$ˆC�ÑØ�W‰WÐ*¨DÓ1ˆØˆ>Ø$&ˆCÐ Ñ!à�8‰8×ÒØ�J‰J�s—x‘x×'Ñ'Ô(àˆ
øô?  ò ñðús   ÆB K
 Ë
	KËKN)r.   r/   r0   r1   r@   r:   © r$   r#   ro   ro   ô   s   „ ÙBà€GóJr$   ro   c                   ó&   ‡ — e Zd ZdZdZˆ fd„Zˆ xZS )Ú
Gateway_u0z°A Gateway class to interface HTTPServer with WSGI u.0.

    WSGI u.0 is an experimental protocol, which uses Unicode for keys
    and values in both Python 2 and Python 3.
    )Úur   c                 óš  •— | j                   }t        t        | �  «       }t	        |j                  «       «      }|j                  dd«      }	 |j                  j                  |«      |d<   |j                  j                  |«      |d<   |j                  |j                  «       «       |S # t        $ r d|d<   |d   |d<   |d   |d<   Y ŒAw xY w)rE   zwsgi.url_encodingzutf-8rr   rs   re   )r=   r   r°   r:   Údictr¨   Ú
setdefaultr“   Údecoder”   ÚUnicodeDecodeErrorr¦   )r   r=   Úenv_10r;   Úencr"   s        €r#   r:   zGateway_u0.get_environO  sÄ   ø€ à�h‰hˆÜ”z 4Ñ4Ó6ˆÜ�6—<‘<“>Ó"ˆð �n‰nÐ0°'Ó:ˆð	9Ø"Ÿx™xŸ™¨sÓ3ˆC�ÑØ"%§&¡&§-¡-°Ó"4ˆC�Ñð 	�
‰
�3—9‘9“;Ôàˆ
øô "ò 	9à'3ˆCÐ#Ñ$Ø% kÑ2ˆC�ÑØ"(¨Ñ"8ˆC�Óð		9ús   Á<B) Â)C
Ã	C
)r.   r/   r0   r1   r@   r:   r4   r5   s   @r#   r°   r°   F  s   ø„ ñð €G÷ð r$   r°   c                   ó   — e Zd ZdZd„ Zd„ Zy)ÚPathInfoDispatcherz6A WSGI dispatcher for dispatch based on the PATH_INFO.c                 ó   — t        j                  t        «      5  t        |j	                  «       «      }ddd«       d„ }|j                  |d¬«       |D ��cg c]  \  }}|j                  d«      |f‘Œ c}}| _        y# 1 sw Y   ŒKxY wc c}}w )z¬Initialize path info WSGI app dispatcher.

        Args:
            apps (dict[str,object]|list[tuple[str,object]]): URI prefix
                and WSGI app pairs
        Nc                 ó   — t        | d   «      S )Nr   )rh   )Úapps    r#   Úby_path_lenz0PathInfoDispatcher.__init__.<locals>.by_path_lenv  s   € Ü�s˜1‘v“;Ðr$   T)ÚkeyÚreverseú/)Ú
contextlibÚsuppressÚAttributeErrorÚlistr¨   ÚsortÚrstripÚapps)r   rÈ   r¾   ÚpÚas        r#   r   zPathInfoDispatcher.__init__k  sw   € ô × Ñ ¤Ó0ñ 	&Ü˜Ÿ
™
›Ó%ˆD÷	&ò	ð 	�	‰	�k¨4ˆ	Ô0ð 59×9©D¨A¨q�a—h‘h˜s“m QÒ'Ó9ˆ�	÷	&ð 	&üó :s   šA>ÁB
Á>Bc                 ó  — |d   xs d}| j                   D ]b  \  }}|j                  |›d�«      s||k(  sŒ |j                  «       }|j                  dd«      |z   |d<   |t	        |«      d |d<    |||«      c S   |dddg«       dgS )	a  Process incoming WSGI request.

        Ref: :pep:`3333`

        Args:
            environ (Mapping): a dict containing WSGI environment variables
            start_response (callable): function, which sets response
                status and headers

        Returns:
            list[bytes]: iterable containing bytes to be returned in
                HTTP response body

        rr   rÁ   ry   ru   Nz404 Not Found)zContent-Typez
text/plain)zContent-LengthÚ0)rÈ   Ú
startswithÚcopyÚgetrh   )r   ÚenvironrI   r“   rÉ   r½   s         r#   Ú__call__zPathInfoDispatcher.__call__  s©   € ð �{Ñ#Ò* sˆØ—i‘iò 	4‰FˆAˆsà�‰ !  a˜yÔ)¨T°Q«YØ!Ÿ,™,›.�Ø)0¯©°]ÀBÓ)GÈ!Ñ)K�˜Ñ&Ø'+¬C°«F¨H ~�˜Ñ$Ù˜7 NÓ3Ò3ð	4ñ 	Øà.Ø'ðô	
ð ˆtˆr$   N)r.   r/   r0   r1   r   rÑ   r®   r$   r#   rº   rº   h  s   „ Ù@ò:ó(r$   rº   )Ú
WSGIServerÚWSGIGatewayÚWSGIGateway_u0ÚWSGIGateway_10ÚWSGIPathInfoDispatcher)r1   rÂ   r›   ru   r   Ú_compatr   r   Úworkersr   Ú
HTTPServerr	   r7   ro   r°   rC   r   rº   Úglobalsr¦   r®   r$   r#   ú<module>rÛ      sŸ   ðñó6 Û 
å ß Ý ôD"ˆV×Ñô D"ôNFˆf�n‰nô FôRO�ô Oôd�ô ð> ×#Ñ#Ó%€÷6ñ 6ñt ƒ	× Ñ ØØØØØ-ð õ r$   