
    Dfj0                       d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z
ddlZddlZddlZddlZddlZddlZddlmZ ddlmZ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 d
Z  ej!                    dk    Z"	  ej#        dd          $                    d          Z%	 e" oe% Z&	 e&r!	 ddl'Z'ddl(Z(n# e)$ r 	 dZ&d\  Z'Z(Y nw xY wddl*Z*e"r2 e+ed          r& e+ed          sde_,         e+ed          sde_-         e+ed          s	 erdnde_.        dZ/dZ0dZ1dZ2dZ3dZ4dZ5d Z6d!Z7d"Z8 ej9        d:                    d#e8f                    Z; e<            Z=g d$Z> e+ed%          si e_?         G d& d'          Z@ G d( d)e@          ZA G d* d+          ZB G d, d-          ZC G d. d/          ZD G d0 d1          ZE G d2 d3          ZF G d4 d5          ZG G d6 d7          ZHd8d9d:ZId=d<ZJdS )>a  
A high-speed, production ready, thread pooled, generic HTTP server.

For those of you wanting to understand internals of this module, here's the
basic call flow. The server's listening thread runs a very tight loop,
sticking incoming connections onto a Queue::

    server = HTTPServer(...)
    server.start()
    ->  serve()
        while ready:
            _connections.run()
                while not stop_requested:
                    child = socket.accept()  # blocks until a request comes in
                    conn = HTTPConnection(child, ...)
                    server.process_conn(conn)  # adds conn to threadpool

Worker threads are kept in a pool and poll the Queue, popping off and then
handling each connection in turn. Each connection can consist of an arbitrary
number of requests and their responses, so we run a nested loop::

    while True:
        conn = server.requests.get()
        conn.communicate()
        ->  while True:
                req = HTTPRequest(...)
                req.parse_request()
                ->  # Read the Request-Line, e.g. "GET /page HTTP/1.1"
                    req.rfile.readline()
                    read_headers(req.rfile, req.inheaders)
                req.respond()
                ->  response = app(...)
                    try:
                        for chunk in response:
                            if chunk:
                                req.write(chunk)
                    finally:
                        if hasattr(response, "close"):
                            response.close()
                if req.close_connection:
                    return

For running a server you can invoke :func:`start() <HTTPServer.start()>` (it
will run the server forever) or use invoking :func:`prepare()
<HTTPServer.prepare()>` and :func:`serve() <HTTPServer.serve()>` like this::

    server = HTTPServer(...)
    server.prepare()
    try:
        threading.Thread(target=server.serve).start()

        # waiting/detecting some appropriate stop condition here
        ...

    finally:
        server.stop()

And now for a trivial doctest to exercise the test suite

.. testsetup::

   from cheroot.server import HTTPServer

>>> 'HTTPServer' in globals()
True
    N)	lru_cache   )connectionserrors__version__)bton)IS_PPC)
threadpool)MakeFileStreamWriter)
HTTPRequestHTTPConnection
HTTPServerHeaderReaderDropUnderscoreHeaderReaderSizeCheckWrapperKnownLengthRFileChunkedRFileGatewayget_ssl_adapter_classWindowsSERVER_SOFTWARE zGoogle App Engine/F)NNAF_INET6IPPROTO_IPV6)   IPV6_V6ONLY   SO_PEERCRED         
s   
   	       :   ;       *   /s   %2Fs   (?i))s   Accepts   Accept-Charsets   Accept-Encodings   Accept-Languages   Accept-Rangess   Allows   Cache-Control
   Connections   Content-Encodings   Content-Language   Expects   If-Matchs   If-None-Matchs   Pragmas   Proxy-Authenticates   TEs   Trailer   Transfer-Encodings   Upgrades   Varys   Vias   Warnings   WWW-Authenticate
statisticsc                   &    e Zd ZdZddZd Zd ZdS )r   z`Object for reading headers from an HTTP request.

    Interface and default implementation.
    Nc                    |i }	 |                                 }|st          d          |t          k    rn|                    t                    st          d          |dd         t          t
          fv r|                                }nh	 |                    t          d          \  }}n# t          $ r t          d          w xY w|                                }| 	                    |          }|}| 
                    |          s|t          v r.|                    |          }|rd                    ||f          }|||<   E|S )a  
        Read headers from the given stream into the given header dict.

        If hdict is None, a new header dict is created. Returns the populated
        header dict.

        Headers which are repeated are folded together using a comma if their
        specification so dictates.

        This function raises ValueError when the read bytes violate the HTTP
        spec.
        You should probably return "400 Bad Request" if this happens.
        NTIllegal end of headers.HTTP requires CRLF terminatorsr   zIllegal header line.s   , )readline
ValueErrorCRLFendswithSPACETABstripsplitCOLON_transform_key_allow_headercomma_separated_headersgetjoin)selfrfilehdictlinevkhnameexistings           =/var/www/media/lib/python3.11/site-packages/cheroot/server.py__call__zHeaderReader.__call__   sh    =E#	>>##D < !:;;;t||==&& C !ABBBBQBxE3<'' JJLL=::eQ//DAqq! = = =$%;<<<=GGII''**%%a(( +++ 99U++ 2

Ha=11AE%LG#	J s   B. .Cc                     dS )NT r@   key_names     rH   r<   zHeaderReader._allow_header   s    tr'   c                 N    |                                                                 S N)r8   titlerL   s     rH   r;   zHeaderReader._transform_key   s    ~~%%'''r'   rO   )__name__
__module____qualname____doc__rI   r<   r;   rK   r'   rH   r   r      sQ         
6 6 6 6p  ( ( ( ( (r'   r   c                   "     e Zd ZdZ fdZ xZS )r   zDCustom HeaderReader to exclude any headers with underscores in them.c                 `    t          t          |                               |          }|od|vS )N_)superr   r<   )r@   rM   orig	__class__s      rH   r<   z(DropUnderscoreHeaderReader._allow_header   s1    /66DDXNN+8++r'   )rQ   rR   rS   rT   r<   __classcell__)rZ   s   @rH   r   r      s>        NN, , , , , , , , ,r'   r   c                   L    e Zd ZdZd Zd ZddZddZddZd	 Z	d
 Z
d ZeZdS )r   zWraps a file-like object, raising MaxSizeExceeded if too large.

    :param rfile: ``file`` of a limited size
    :param int maxlen: maximum length of the file being read
    c                 0    || _         || _        d| _        dS )z%Initialize SizeCheckWrapper instance.r   N)rA   maxlen
bytes_read)r@   rA   r^   s      rH   __init__zSizeCheckWrapper.__init__  s    
r'   c                 ^    | j         r#| j        | j         k    rt          j                    d S d S rO   )r^   r_   r   MaxSizeExceededr@   s    rH   _check_lengthzSizeCheckWrapper._check_length  s9    ; 	+4?T[88(***	+ 	+88r'   Nc                     | j                             |          }| xj        t          |          z  c_        |                                  |S )Read a chunk from ``rfile`` buffer and return it.

        :param size: amount of data to read
        :type size: int

        :returns: chunk from ``rfile``, limited by size if specified
        :rtype: bytes
        )rA   readr_   lenrd   r@   sizedatas      rH   rg   zSizeCheckWrapper.read  sD     zt$$3t99$r'   c                    |M| j                             |          }| xj        t          |          z  c_        |                                  |S g }	 | j                             d          }| xj        t          |          z  c_        |                                  |                    |           t          |          dk     s|dd         t          k    rt                              |          S )Read a single line from ``rfile`` buffer and return it.

        :param size: minimum amount of data to read
        :type size: int

        :returns: one line from ``rfile``
        :rtype: bytes
        NT   )	rA   r2   r_   rh   rd   appendLFEMPTYr?   )r@   rj   rk   ress       rH   r2   zSizeCheckWrapper.readline  s     :&&t,,DOOs4yy(OO   K 	':&&s++DOOs4yy(OO   JJt4yy3$rss)r//zz#&	'r'   r   c                     d}g }|                      |          }|rO|                    |           |t          |          z  }d|cxk     r|k    rn nn|                      |          }|O|S zRead all lines from ``rfile`` buffer and return them.

        :param sizehint: hint of minimum amount of data to read
        :type sizehint: int

        :returns: lines of bytes read from ``rfile``
        :rtype: list[bytes]
        r   r2   rp   rh   r@   sizehinttotallinesrC   s        rH   	readlineszSizeCheckWrapper.readlines9       }}X&& 	+LLSYYE8$$$$u$$$$$==**D  	+ r'   c                 8    | j                                          dS z*Release resources allocated for ``rfile``.NrA   closerc   s    rH   r   zSizeCheckWrapper.closeN      
r'   c                     | S zReturn file iterator.rK   rc   s    rH   __iter__zSizeCheckWrapper.__iter__R      r'   c                     t          | j                  }| xj        t          |          z  c_        |                                  |S zGenerate next file chunk.)nextrA   r_   rh   rd   r@   rk   s     rH   __next__zSizeCheckWrapper.__next__V  s>    DJ3t99$r'   rO   r   )rQ   rR   rS   rT   r`   rd   rg   r2   r{   r   r   r   r   rK   r'   rH   r   r      s           + + +   ' ' ' '6   *       DDDr'   r   c                   F    e Zd ZdZd ZddZddZddZd Zd	 Z	d
 Z
e
ZdS )r   zWraps a file-like object, returning an empty string when exhausted.

    :param rfile: ``file`` of a known size
    :param int content_length: length of the file being read
    c                 "    || _         || _        dS )z%Initialize KnownLengthRFile instance.N)rA   	remaining)r@   rA   content_lengths      rH   r`   zKnownLengthRFile.__init__g  s    
'r'   Nc                     | j         dk    rdS || j         }nt          || j                   }| j                            |          }| xj         t	          |          z  c_         |S )zRead a chunk from ``rfile`` buffer and return it.

        :param size: amount of data to read
        :type size: int

        :rtype: bytes
        :returns: chunk from ``rfile``, limited by size if specified
        r   r'   )r   minrA   rg   rh   ri   s      rH   rg   zKnownLengthRFile.readl  sc     >Q3<>DDtT^,,Dzt$$#d))#r'   c                     | j         dk    rdS || j         }nt          || j                   }| j                            |          }| xj         t	          |          z  c_         |S )rm   r   r'   )r   r   rA   r2   rh   ri   s      rH   r2   zKnownLengthRFile.readline  se     >Q3<>DDtT^,,Dz""4((#d))#r'   r   c                     d}g }|                      |          }|rO|                    |           |t          |          z  }d|cxk     r|k    rn nn|                      |          }|O|S ru   rv   rw   s        rH   r{   zKnownLengthRFile.readlines  r|   r'   c                 8    | j                                          dS r~   r   rc   s    rH   r   zKnownLengthRFile.close  r   r'   c                     | S r   rK   rc   s    rH   r   zKnownLengthRFile.__iter__  r   r'   c                 h    t          | j                  }| xj        t          |          z  c_        |S r   )r   rA   r   rh   r   s     rH   r   zKnownLengthRFile.__next__  s,    DJ#d))#r'   rO   r   )rQ   rR   rS   rT   r`   rg   r2   r{   r   r   r   r   rK   r'   rH   r   r   `  s         ( ( (
   (   (   *       DDDr'   r   c                   D    e Zd ZdZddZd ZddZddZdd	Zd
 Z	d Z
dS )r   a  Wraps a file-like object, returning an empty string when exhausted.

    This class is intended to provide a conforming wsgi.input value for
    request entities that have been encoded with the 'chunked' transfer
    encoding.

    :param rfile: file encoded with the 'chunked' transfer encoding
    :param int maxlen: maximum length of the file being read
    :param int bufsize: size of the buffer used to read the file
        c                 d    || _         || _        d| _        t          | _        || _        d| _        dS )z!Initialize ChunkedRFile instance.r   FN)rA   r^   r_   rr   bufferbufsizeclosed)r@   rA   r^   r   s       rH   r`   zChunkedRFile.__init__  s0    
r'   c                 |   | j         rd S | j                                        }| xj        t	          |          z  c_        | j        r*| j        | j        k    rt          j        d| j                  |                                	                    t          d          }	 |                    d          }t          |d          }n1# t          $ r$ t          d                    |                    w xY w|dk    r	d| _         d S | j        r"| j        |z   | j        k    rt          d          | j                            |          }| xj        t	          |          z  c_        | xj        |z  c_        | j                            d          }|t$          k    r"t          d	t'          |          z   d
z             d S )NRequest Entity Too Larger   r      z)Bad chunked transfer size: {chunk_size!r})
chunk_sizeT   z2Bad chunked transfer coding (expected '\r\n', got ))r   rA   r2   r_   rh   r^   r   rb   r8   r9   	SEMICOLONpopintr3   formatIOErrorrg   r   r4   repr)r@   rC   r   chunkcrlfs        rH   _fetchzChunkedRFile._fetch  s   ; 	Fz""$$3t99$; 	4?T[88(*DK   zz||!!)Q//	!JZ,,JJ 	 	 	;*--  	 ??DKF ; 	64?Z7$+EE4555

++3u::%uzq!!4<<d$&)*   <s   %C .C3Nc                 <   t           }|dk    r|S 	 |rt          |          |k    r|S | j        s|                                  | j        s|S |r9|t          |          z
  }|| j        d|         z  }| j        |d         | _        n|| j        z  }t           | _        )rf   r   TN)rr   rh   r   r   )r@   rj   rk   r   s       rH   rg   zChunkedRFile.read  s     199K	$ D		T));  {  K $ 3t99,	JYJ//"k)**5##!	$r'   c                 p   t           }|dk    r|S 	 |rt          |          |k    r|S | j        s|                                  | j        s|S | j                            t
                    }|r|dk    r9|t          |          z
  }|| j        d|         z  }| j        |d         | _        nt          |t          |          z
  |          }|| j        d|         z  }| j        |d         | _        nC|dk    r|| j        z  }t           | _        n&|| j        d|         z  }| j        |d         | _        ')rm   r   Tro   N)rr   rh   r   r   findrq   r   )r@   rj   rk   newline_posr   s        rH   r2   zChunkedRFile.readline  sO    199K	< D		T));  {  K+**2..K <"$$ $s4yy 0IDK

33D"&+ijj"9DKK #D3t99$4k B BIDK

33D"&+ijj"9DKK"$$DK'D"'DKKDK55D"&+kll";DK5	<r'   r   c                     d}g }|                      |          }|rO|                    |           |t          |          z  }d|cxk     r|k    rn nn|                      |          }|O|S ru   rv   rw   s        rH   r{   zChunkedRFile.readlinesD  r|   r'   c              #     K   | j         st          d          	 | j                                        }|st          d          | xj        t          |          z  c_        | j        r| j        | j        k    rt          d          |t          k    rdS |	                    t                    st          d          |V  )zhRead HTTP headers and yield them.

        :yields: CRLF separated lines
        :ytype: bytes

        z:Cannot read trailers until the request body has been read.Tr0   r   r1   N)
r   r3   rA   r2   r_   rh   r^   r   r4   r5   )r@   rC   s     rH   read_trailer_lineszChunkedRFile.read_trailer_linesY  s       { 	L  	:&&((D < !:;;;OOs4yy(OO{ :t<<8999t||==&& C !ABBBJJJ!	r'   c                 8    | j                                          dS r~   r   rc   s    rH   r   zChunkedRFile.closew  r   r'   )r   rO   r   )rQ   rR   rS   rT   r`   r   rg   r2   r{   r   r   rK   r'   rH   r   r     s        	 	   ) ) )V$ $ $ $@(< (< (< (<T   *  <    r'   r   c                       e Zd ZdZdZ	 dZ	 i Z	 g Z	 dZ	 dZ		 dZ
	  e            Z	 ddZd Zd Zd Zd	 ZddZd Zd Zd ZdS )r   zrAn HTTP Request (and response).

    A single HTTP connection may consist of multiple request/response pairs.
    NFTc                 &   || _         || _        d| _        d| _        d| _        | j         j        d| _        d| _        i | _        d| _        g | _	        d| _
        | j        j        | _        d| _        | j        j        | _        || _        || _        dS )a  Initialize HTTP request container instance.

        Args:
            server (HTTPServer): web server object receiving this request
            conn (HTTPConnection): HTTP connection object for this request
            proxy_mode (bool): whether this HTTPServer should behave as a PROXY
            server for certain requests
            strict_mode (bool): whether we should return a 400 Bad Request when
            we encounter a request that a HTTP compliant client should not be
            making
        Fs   httpNs   httpszHTTP/1.0r   )serverconnreadystarted_requestschemessl_adapterresponse_protocol	inheadersstatus
outheaderssent_headersrZ   close_connectionchunked_readchunked_write
proxy_modestrict_mode)r@   r   r   r   r   s        rH   r`   zHTTPRequest.__init__  s     	
$;"."DK!+! $ ?!!^9$&r'   c                 ~   t          | j        j        | j        j                  | _        	 |                                 }|sdS n,# t          j        $ r |                     dd           Y dS w xY w	 | 	                                }|sdS n,# t          j        $ r |                     dd           Y dS w xY wd| _
        dS )z;Parse the next HTTP request start-line and message-headers.Nz414 Request-URI Too LongzHThe Request-URI sent with the request exceeds the maximum allowed bytes.413 Request Entity Too LargezCThe headers sent with the request exceed the maximum allowed bytes.T)r   r   rA   r   max_request_header_sizeread_request_liner   rb   simple_responseread_request_headersr   )r@   successs     rH   parse_requestzHTTPRequest.parse_request  s   %IOK/
 

	,,..G   % 	 	 	  *!  
 FF		//11G   % 	 	 	  .!  
 FF	 


s#   A %A-,A-1B
 
%B32B3c                 
   | j                                         }d| _        |sdS |t          k    r| j                                         }|sdS |                    t                    s|                     dd           dS 	 |                                                    t          d          \  }}}|	                    d          s|                     dd           dS |dd	                             d
d          }t          |          dk    r|                     dd           dS t          t          t          |                    }|dk    r|                     dd           dS n.# t          t          f$ r |                     dd           Y dS w xY w|| _        |                                | _        | j        r%|| j        k    rd}|                     d|           dS 	 t(          j                            |          \  }}}	}
}n'# t.          $ r |                     dd           Y dS w xY w|p|}| j        dk    r| j        r|r|n|	}	n| j        dk    r| j        s|                     d           dS t(          j                            d                    d|f                    }|\  }}}}}t4          }	 |j        }n# t          $ r Y nw xY w||k    p| pt9          ||||f          }|r|                     dd           dS |x}}	t4          x}x}
}n| j        o	| j         o|}|r	 |                     dd           dS | j        o|	                    t:                     o| }|r	 d}|                     d|           dS |r|                     dd           dS |	|                     dd           dS 	 d t<                              |	          D             }n9# t          $ r,}|                     d|j        d                    Y d	}~dS d	}~ww xY wt@                              |          }	|		                    t:                    s
t:          |	z   }	|t4          ur|| _!        || _"        |	| _#        |
| _$        t          | j%        j&        d                   t          | j%        j&        d                   f}|d         |d         k    r|                     d           dS || _'        d tQ          ||          z  | _)        dS )!zRead and parse first line of the HTTP request.

        Returns:
            bool: True if the request line is valid or False if it's malformed.

        TF400 Bad Requestr1   r   s   HTTP/z$Malformed Request-Line: bad protocol   N   .r   z#Malformed Request-Line: bad version)r   r   z505 HTTP Version Not SupportedzCannot fulfill requestzMalformed Request-LinezMalformed method name: According to RFC 2616 (section 5.1.1) and its successors RFC 7230 (section 3.1.1) and RFC 7231 (section 4.1) method names are case-sensitive and uppercase.zMalformed Request-URIs   OPTIONSs   CONNECTz405 Method Not Allowedr'   s   //zFInvalid path in Request-URI: request-target must match authority-form.z2Absolute URI not allowed if server is not a proxy.zInvalid path in Request-URI: request-target must contain origin-form which starts with absolute-path (URI starting with a slash "/").z!Illegal #fragment in Request-URI.zInvalid path in Request-URI.c                 L    g | ]!}t           j                            |          "S rK   )urllibparseunquote_to_bytes.0xs     rH   
<listcomp>z1HTTPRequest.read_request_line.<locals>.<listcomp>  s8        L11!44  r'   r      z
HTTP/%s.%s)*rA   r2   r   r4   r5   r   r8   r9   r6   
startswithrh   tuplemapr   r3   
IndexErroruriuppermethodr   r   r   urlsplitUnicodeErrorr   r?   rr   portanyFORWARD_SLASHQUOTED_SLASH_REGEXargsQUOTED_SLASHr   	authoritypathqsr   protocolrequest_protocolr   r   )r@   request_liner   r   req_protocolrprespr   r   r   r   fragmenturi_is_absolute_form	uri_split_scheme
_authority_path_qs	_fragment_portinvalid_pathdisallowed_absoluteatomsexsps                            rH   r   zHTTPRequest.read_request_line  sV    z**,,  $ 	54
  :..00L u$$T** 	  !#C   5	(4(:(:(<(<(B(B5!(L(L%FC**844 $$%'M   uabb!''a00B2ww!||$$%'L   us3||$$BF{{$$46N   u	 
 J' 	 	 	  !24LMMM55	 llnn 	$+ 5 5A    !2D9995	4:L4I4I#4N4N1FItR 	 	 	  !24KLLL55	 !' 3);*$$
 O(< 	 D [J&&? $$%=>>>u --chhs|.D.DEEI9B6GZYE!    c! 999Y788 
  $$%8  
 u))I%**F*R((   )')(  
 #  C$$%H   u   -}555-,, 
  
 >2 
 $$%6===u $$%7   u|$$%2   u	 /55d;;      $$%6
CCCuuuuu  $$U++D}-- 	( 4'D DK"	  %a())3t{/CA/F+G+GGa5BqE>>  !ABBB5 ,!-B!;ts\    AE( AE( '>E( ('FF#%H	 	 H-,H-;K 
KK=$O" "
P,!PPc                    	 |                      | j        | j                   n9# t          $ r,}|                     d|j        d                    Y d}~dS d}~ww xY w| j        j        }	 t          | j        	                    dd                    }n'# t          $ r |                     dd           Y dS w xY w|r||k    r|                     dd           dS | j
        d	k    r'| j        	                    d
d          dk    rd| _        n&| j        	                    d
d          dk    rd| _        d}| j
        d	k    r;| j        	                    d          }|rd |                    d          D             }d| _        |r1|D ].}|dk    rd| _        |                     d           d| _         dS | j        	                    dd          dk    rd                    | j        j                            d          t"          dt$          t$          f          }	 | j        j                            |           n6# t,          j        $ r$}|j        d         t0          j        vr Y d}~nd}~ww xY wdS )zRead ``self.rfile`` into ``self.inheaders``.

        Ref: :py:attr:`self.inheaders <HTTPRequest.outheaders>`.

        :returns: success status
        :rtype: bool
        r   r   NF   Content-Lengthz Malformed Content-Length Header.r   CThe entity sent with the request exceeds the maximum allowed bytes.HTTP/1.1r*   r'      closeT
   Keep-Aliver,   c                     g | ]<}|                                 |                                                                 =S rK   )r8   lowerr   s     rH   r   z4HTTPRequest.read_request_headers.<locals>.<listcomp>  s7    MMMA17799Maggiioo''MMMr'      ,   chunkedz501 Unimplementedr+   s   100-continueasciis   100 Continue)header_readerrA   r   r3   r   r   r   max_request_body_sizer   r>   r   r   r9   r   r?   r   encoder6   r4   r   wfilewritesocketerrorr   socket_errors_to_ignore)r@   r   mrbsclteencmsgs          rH   r   z HTTPRequest.read_request_headers  s   	tz4>:::: 	 	 	  !2BGAJ???55555	 {0	T^''(91==>>BB 	 	 	  !2   55	  	BII  .!  
 5 !Z//~!!-55AA(,% ~!!-55FF(,% !Z//##$899B NMM$MMM! 		! ! !*$$(,D%% (()<===,0D) 55& >i--@@ (($++G44e_d  C	%%c****<   71:V%CCC DCCCC ts>    # 
A!AA)(B  B65B6H9 9I,I''I,c                 &   | j         j        }| j        r t          | j        j        |          | _        nnt          | j                            dd                    }|r%||k     r| j	        s| 
                    dd           dS t          | j        j        |          | _        | j                             |                                            | j        o|                                  | j        r!| j        j                            d           dS dS )z/Call the gateway and write its iterable output.r  r   r   r  Ns   0

)r   r  r   r   r   rA   r   r   r>   r   r   r   gatewayrespondr   ensure_headers_sentr   r  r  )r@   r  r  s      rH   r  zHTTPRequest.respond(  s   {0 	?%diot<<DJJT^''(91==>>B r		( ((61  
 )$)/2>>DJD!!))+++
1t//11 	0IO!!,/////	0 	0r'   r   c                    t          |          }| j        j        d|d}dt          |          z  }d}|                    d          |                    d          |                    d          g}|dd         dv r*d	| _        | j        d
k    r|                    d           nd}|                    t                     |r?t          |t                     r|                    d          }|                    |           	 | j
        j                            t                              |                     dS # t          j        $ r%}|j        d         t$          j        vr Y d}~dS d}~ww xY w)z+Write a simple response back to the client. z
zContent-Length: %s
zContent-Type: text/plain

ISO-8859-1N   )413414Tr  s   Connection: close
r   r   )strr   r   rh   r  r   r   rp   r4   
isinstancer   r  r  rr   r?   r  r  r   r   r  )r@   r   r  proto_statusr   content_typebufr   s           rH   r   zHTTPRequest.simple_response?  s   V&*k&:&:&:FFFC1CHH<5--!!,//--
 "1":''$(D!%33 

34444 +

4 	#s## /jj..JJsOOO	IO!!%**S//22222| 	 	 	wqz!??? @?????	s   7D? ?E3E..E3c                 N    | j         sd| _         |                                  dS dS )z:Ensure headers are sent to the client if not already sent.TN)r   send_headersrc   s    rH   r  zHTTPRequest.ensure_headers_sentd  s7      	  $D	  	 r'   c                 V   | j         r|rt          t          |                    dd                             d          }|t          |t          g}| j        j                            t          	                    |                     dS | j        j                            |           dS )z$Write unbuffered data to the client.r   Nr  )
r   hexrh   r  r4   r   r  r  rr   r?   )r@   r   chunk_size_hexr'  s       rH   r  zHTTPRequest.writej  s     	)% 	) U__QRR077@@N!45CIO!!%**S//22222IO!!%(((((r'   c                    d | j         D             }t          | j        dd                   }|dk    rd| _        nPd|vrL|dk     s|dv rnA| j        d	k    o
| j        d
k    }|r"d| _        | j                             d           nd| _        | j        s| j        j	        }| | _        d|vrN| j        d	k    r"| j        r| j                             d           n!| j        s| j                             d           d| j         v rM| j                             dd
                    | j        j                                      d          f           | j        s=| j        s6t          | j        dd          }|dk    r| j                            |           d|vrM| j                             dt"          j                            d                              d          f           d|vr9| j                             d| j        j                            d          f           | j        j                            d          }|t,          z   | j        z   t.          z   g}| j         D ]5\  }}	|                    |t0          z   t,          z   |	z   t.          z              6|                    t.                     | j        j                            t8                              |                     dS )zAssert, process, and send the HTTP response message-headers.

        You must set ``self.status``, and :py:attr:`self.outheaders
        <HTTPRequest.outheaders>` before calling this.
        c                 <    g | ]\  }}|                                 S rK   )r  )r   keyvalues      rH   r   z,HTTPRequest.send_headers.<locals>.<listcomp>y  s$    ???e???r'   Nr   i  Ts   content-length   )      i0  r  s   HEAD)r,   r
  s
   connection)r*   r  )r*   r  r  ztimeout={connection_timeout})connection_timeoutr  r   r   s   dates   Date)usegmts   servers   Serverr  )r   r   r   r   r   r   r   rp   r   can_add_keepalive_connectionr   timeoutr  r   getattrrA   rg   emailutils
formatdateserver_namer   r6   r4   r:   r   r  r  rr   r?   )
r@   hkeysr   needs_chunkedcan_keepr   protor'  rE   rD   s
             rH   r)  zHTTPRequest.send_headerss  s    @?t???T[!_%%S==$(D!!e++ ||v88 *j8 /w.  ! 1)-D&O**+MNNNN -1D) $ 	1{?H(0LD!%%%33( FO**+DEEE , KO**+IJJJ)T_<<O""/$+*=>>|$$	$    % 	+0A 	+  
K;;I1}}
	***%O""&&d&33::<HH$   
 E!!O""'..|<<$   
 $++G44u}t{*T12O 	5 	5DAqJJq5y5(1,t34444

4	ejjoo.....r'   )FT)r   )rQ   rR   rS   rT   r   r   r   r   r   r   r   r   r  r`   r   r   r   r  r   r  r  r)  rK   r'   rH   r   r   |  s        
 F@DDI$J;E@  M< !LNNM' ' ' 'B     Da a aF^ ^ ^@0 0 0.# # # #J     ) ) )Y/ Y/ Y/ Y/ Y/r'   r   c                       e Zd ZdZdZdZdZej        Z	ej        Z
eZdZdZdZefdZd ZdZd Zd Zd Zd	 Zed
             Zed             Zed             Zd Zed             Zed             Zd ZdS )r   z#An HTTP connection (active socket).NFc                 \   || _         || _         ||d| j                  | _         ||d| j                  | _        d| _        | j         j        | _        | j         j        | _         t          d          | j
                  | _
         t          d          | j                  | _        dS )aB  Initialize HTTPConnection instance.

        Args:
            server (HTTPServer): web server object receiving this request
            sock (socket._socketobject): the raw socket object (usually
                TCP) for this connection
            makefile (file): a fileobject class for reading from the socket
        rbwbr   r   )maxsizeN)r   r  rbufsizerA   wbufsizer  requests_seenpeercreds_enabledpeercreds_resolve_enabledr   resolve_peer_credsget_peer_creds)r@   r   sockmakefiles       rH   r`   zHTTPConnection.__init__  s     XdD$-88
XdD$-88
!%!>)-)N&
 !Ia   !899 	 !Ia   !455 	r'   c                    d}	 |                      | j        |           }|                                 | j        j        d         r| xj        dz  c_        |j        sdS d}|                                 |j        sdS nN# t          j	        $ r}|j
        d         }d}||v r"|r	|r|j        r|                     |d           n[|t          j        vrM| j                            dt!          |          z  t"          j        d	           |                     |d
           Y d}~nd}~wt&          t(          f$ r  t          j        $ r Y nt          j        $ r |                     |           Y n`t0          $ rT}| j                            t!          |          t"          j        d	           |                     |d
           Y d}~nd}~ww xY wdS )zrRead each request and respond appropriately.

        Returns true if the connection should be kept open.
        FEnabledr   Tr   )z	timed outzThe read operation timed outz408 Request Timeoutzsocket.error %slevel	tracebackz500 Internal Server ErrorN)RequestHandlerClassr   r   statsrH  r   r  r   r  r  r   r   _conditional_errorr   r  	error_logr   loggingWARNINGKeyboardInterrupt
SystemExitFatalSSLAlert
NoSSLError_handle_no_ssl	ExceptionERROR)r@   request_seenreqr   errnumtimeout_errss         rH   communicatezHTTPConnection.communicate  sE   
 *	F**4;==C{ + (""a'""9  uLKKMMM' t| 	J 	J 	JWQZFFL%%
 % H# H#2E H++C1FGGGv===%%%V4!/T &    ''-HIII!:. 	 	 	# 	 	 	D  	% 	% 	%$$$$$ 	F 	F 	FK!!R "    ##C)DEEEEEEEE		F
 us8   AA? A? ?G
BD###G
#G
-	G
6A
GG
c                     |r|j         rd S 	 | j        j        }n# t          $ r | j        j        }Y nw xY wt          |d| j                  | _        d}|                    d|           d| _	        d S )NrD  zUThe client sent a plain HTTP request, but this server only speaks HTTPS on this port.r   T)
r   r  _sockAttributeError_socketr   rG  r  r   linger)r@   rb  	resp_sockr  s       rH   r^  zHTTPConnection._handle_no_ssl.  s     	c& 	F	,)II 	, 	, 	,+III	, ")T4=AA
: 	 	-s333s    33c                     |r|j         rdS 	 |                    |           dS # t          j        $ r Y dS t          j        $ r |                     |           Y dS w xY w)zvRespond with an error.

        Don't bother writing if a response
        has already started being written.
        N)r   r   r   r\  r]  r^  )r@   rb  responses      rH   rV  z!HTTPConnection._conditional_error?  s      	c& 	F	%)))))# 	 	 	DD  	% 	% 	%$$$$$$	%s   $ A#AAc                     | j                                          | j        s/|                                  | j                                         dS dS )z,Close the socket underlying this connection.N)rA   r   rj  _close_kernel_socketr  rc   s    rH   r   zHTTPConnection.closeO  sU    
{ 	%%''' K Dr'   c                    d}t           s| j        j        t          j        k    rt	          d          | j        st          d          	 | j                            t          j        t          j	        t          j        |                    }t          j        ||          \  }}}|||fS # t          j        $ r}	 t          |d}~ww xY w)a  Return the PID/UID/GID tuple of the peer socket for UNIX sockets.

        This function uses SO_PEERCRED to query the UNIX PID, UID, GID
        of the peer, which is only available if the bind address is
        a UNIX domain socket.

        Raises:
            NotImplementedError: in case of unsupported socket type
            RuntimeError: in case of SO_PEERCRED lookup unsupported or disabled

        3iz5SO_PEERCRED is only supported in Linux kernel and WSLz0Peer creds lookup is disabled within this serverN)
IS_WINDOWSr  familyAF_UNIXNotImplementedErrorrI  RuntimeError
getsockopt
SOL_SOCKETr   structcalcsizeunpackr  )r@   PEERCRED_STRUCT_DEF
peer_credspiduidgid
socket_errs          rH   rL  zHTTPConnection.get_peer_credsb  s     # 	+v~==%G   ' 	B  	!// !6#5 344	 J  #M*=zJJMCcS=  | 	/ 	/ 	/ J.	/s   
AB* *C9	CCc                 6    |                                  \  }}}|S )z,Return the id of the connected peer process.rL  )r@   r~  rW   s      rH   peer_pidzHTTPConnection.peer_pid  s      ''))	Q
r'   c                 6    |                                  \  }}}|S )z1Return the user id of the connected peer process.r  )r@   rW   r  s      rH   peer_uidzHTTPConnection.peer_uid  s      ''))	3
r'   c                 6    |                                  \  }}}|S )z2Return the group id of the connected peer process.r  )r@   rW   r  s      rH   peer_gidzHTTPConnection.peer_gid  s      ''))	1c
r'   c                     t           st          d          | j        st          d          t	          j        | j                  j        }t          j	        | j
                  j        }||fS )a  Look up the username and group tuple of the ``PEERCREDS``.

        :returns: the username and group tuple of the ``PEERCREDS``

        :raises NotImplementedError: if the OS is unsupported
        :raises RuntimeError: if UID/GID lookup is unsupported or disabled
        zUID/GID lookup is unavailable under current platform. It can only be done under UNIX-like OS but not under the Google App Enginez-UID/GID lookup is disabled within this server)IS_UID_GID_RESOLVABLEru  rJ  rv  pwdgetpwuidr  pw_namegrpgetgrgidr  gr_name)r@   usergroups      rH   rK  z!HTTPConnection.resolve_peer_creds  sy     % 		%6  
 / 	?   |DM**2T]++3U{r'   c                 4    |                                  \  }}|S )z2Return the username of the connected peer process.rK  )r@   r  rW   s      rH   	peer_userzHTTPConnection.peer_user  s     ))++ar'   c                 4    |                                  \  }}|S )z/Return the group of the connected peer process.r  )r@   rW   r  s      rH   
peer_groupzHTTPConnection.peer_group  s     **,,5r'   c                     t          | j        d| j        j                  }	  |t          j                   dS # t          j        $ r Y dS t          j        $ r}|j        t          j        vr Y d}~dS d}~ww xY w)z0Terminate the connection at the transport level.sock_shutdownN)	r8  r  shutdown	SHUT_RDWRr   #acceptable_sock_shutdown_exceptionsr  errno$acceptable_sock_shutdown_error_codes)r@   r  es      rH   ro  z#HTTPConnection._close_kernel_socket  s     KK 
 

	HV%&&&&&9 	 	 	DD| 	 	 	wfIII JIIIII	s   9 A8A8A33A8) rQ   rR   rS   rT   remote_addrremote_portssl_envioDEFAULT_BUFFER_SIZErF  rG  r   rT  rI  rJ  	last_usedr   r`   re  rj  r^  rV  r   rL  propertyr  r  r  rK  r  r  ro  rK   r'   rH   r   r     sb       --KKG%H%H% % I.6 
 
 
 
61 1 1f F  "% % %   &)! )! )!V   X
   X
   X
  0   X
   X
    r'   r   c                   4   e Zd ZdZdZdZdZ	 dZ	 dZ	 dZ		 dZ
	 dZ	 dZ	 dZ	 dZ	 d                    e	          Z	 dZ	 d
Z	 dZ	 dZ	 dZ	 eZ	 dZ	 d
Z	 d
Z	 d
Z	 dZ	 	 	 	 d)dZd Zd Z d Z!e"d             Z#e#j$        d             Z#d Z%d Z&d Z'd Z(e)j*        d             Z+e"d             Z,d Z-d*dZ.d+dZ/d Z0e1d              Z2e3	 d,d!            Z4e1d"             Z5e1d#             Z6d$ Z7e"d%             Z8e"d&             Z9e8j$        d'             Z8d( Z:dS )-r   zAn HTTP server.z	127.0.0.1Nr  r   
   g      ?zCheroot/{version!s})versionFr   Tro   c	                     || _         || _        t          j        | |pd|          | _        |s| j        }|| _        || _        |o|| _        || _	        | 
                                 dS )a  Initialize HTTPServer instance.

        Args:
            bind_addr (tuple): network interface to listen to
            gateway (Gateway): gateway for processing HTTP requests
            minthreads (int): minimum number of threads for HTTP thread pool
            maxthreads (int): maximum number of threads for HTTP thread pool
            server_name (str): web server name to be advertised via Server
                HTTP header
            reuse_port (bool): if True SO_REUSEPORT option would be set to
                socket
        r   )r   maxN)	bind_addrr  r
   
ThreadPoolrequestsr  r<  rI  rJ  
reuse_portclear_stats)	r@   r  r  
minthreads
maxthreadsr<  rI  rJ  r  s	            rH   r`   zHTTPServer.__init__3  s    $ #"-joA:
 
 
  	',K&!2%;*; 	& %r'   c                 
    d _         d _        i ddd fdd fdd	dd
 fdd fdd fdd fddddd dd dd dd dd dd di  _         j        t          j        d t                     z  <   dS )!zReset server stat counters..Nr   rP  FzBind Addressc                 ,    t          j                  S rO   )r   r  sr@   s    rH   <lambda>z(HTTPServer.clear_stats.<locals>.<lambda>\  s    d4>&:&: r'   zRun timec                 B    | d          rdp                                 S )NrP  ro   runtimer  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>]  s     q|#3";"Mt||~~ r'   AcceptszAccepts/secc                 >    | d                                          z  S )Nr  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>_  s    Qy\DLLNN%B r'   Queuec                 0    t          j        dd           S )Nqsizer8  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>`  s    wt}gtDD r'   Threadsc                 J    t          t          j        dg                     S )N_threads)rh   r8  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>a  s    WT]J%K%K!L!L r'   zThreads Idlec                 0    t          j        dd           S )Nidler  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>b  s    gdmVT&J&J r'   zSocket ErrorsRequestsc                 |    | d          rdp1t          d | d                                         D             d          S )NrP  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r   ws     rH   	<genexpr>z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>e  s0      HHa:q!!HHHHHHr'   Worker Threadsr   sumvaluesr  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>d  sJ    q|#3"; #sHH1-=+>+E+E+G+GHHH!@ @ r'   
Bytes Readc                 |    | d          rdp1t          d | d                                         D             d          S )NrP  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>h  s0      JJ<##JJJJJJr'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>g  sJ    9%5$=2 %JJQ/?-@-G-G-I-IJJJAB B r'   Bytes Writtenc                 |    | d          rdp1t          d | d                                         D             d          S )NrP  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>k  s2      MM1#?#A&&MMMMMMr'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>j  sK    AiL(8'@b (CMM2B0C0J0J0L0LMMME E r'   	Work Timec                 |    | d          rdp1t          d | d                                         D             d          S )NrP  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>o  s0      IIq;""IIIIIIr'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>n  sJ    )$4#<" $IIA.>,?,F,F,H,HIII1A A r'   zRead Throughputc                 |    | d          rdp1t          d | d                                         D             d          S )NrP  ro   c              3   `   K   | ])} |d          |           |d         |          pdz  V  *dS )r  r  ư>NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>r  s\         $AlOA&&.!K.*;*;*CtD     r'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>q  sX    a	l*:)B *c /07799   	G G r'   zWrite Throughputc                 |    | d          rdp1t          d | d                                         D             d          S )NrP  ro   c              3   `   K   | ])} |d          |           |d         |          pdz  V  *dS )r  r  r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>x  s]         'Ao&q))^Q{^A->->-F$G     r'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>w  sX    q|+;*C +s /07799   	H H r'   r  zCheroot HTTPServer %d)_start_time	_run_timerU  rX  r-   idrc   s   `rH   r  zHTTPServer.clear_statsV  sk   $
u$
::::$
 MMMM$
 q	$

 BBBB$
 DDDD$
 LLLL$
 JJJJ$
 Q$
   $
   $
    !$
(   )$
.     /$
:  ! !;$
F bG$

J BF2RXX=>>>r'   c                 d    | j         | j        S | j        t          j                    | j         z
  z   S )zReturn server uptime.)r  r  timerc   s    rH   r  zHTTPServer.runtime  s.    #>!>TY[[43C%CDDr'   c                 @    | j         d| j        j        d| j        dS )z1Render Server instance representing bind address..(r   )rR   rZ   rQ   r  rc   s    rH   __str__zHTTPServer.__str__  s-     OOOT^444NNN
 	
r'   c                     | j         S )a  Return the interface on which to listen for connections.

        For TCP sockets, a (host, port) tuple. Host values may be any
        :term:`IPv4` or :term:`IPv6` address, or any valid hostname.
        The string 'localhost' is a synonym for '127.0.0.1' (or '::1',
        if your hosts file prefers :term:`IPv6`).
        The string '0.0.0.0' is a special :term:`IPv4` entry meaning
        "any active interface" (INADDR_ANY), and '::' is the similar
        IN6ADDR_ANY for :term:`IPv6`.
        The empty string or :py:data:`None` are not allowed.

        For UNIX sockets, supply the file name as a string.

        Systemd socket activation is automatic and doesn't require tempering
        with this variable.

        .. glossary::

           :abbr:`IPv4 (Internet Protocol version 4)`
              Internet Protocol version 4

           :abbr:`IPv6 (Internet Protocol version 6)`
              Internet Protocol version 6
        )
_bind_addrrc   s    rH   r  zHTTPServer.bind_addr  s    4 r'   c                 p    t          |t                    r|d         dv rt          d          || _        dS )z5Set the interface on which to listen for connections.r   )r   NzzHost values of '' or None are not allowed. Use '0.0.0.0' (IPv4) or '::' (IPv6) instead to listen on all active interfaces.N)r$  r   r3   r  )r@   r0  s     rH   r  zHTTPServer.bind_addr  sJ     eU## 	aJ(>(> 6  
  r'   c                     	 |                                   dS # t          $ r}| j        }|s|| _        ||d}~wt          $ r}| j        }|s|| _        ||d}~ww xY w)z4Run the server forever, and stop it cleanly on exit.N)startrZ  	interruptr[  )r@   kb_intr_excunderlying_interruptsys_exit_excs       rH   
safe_startzHTTPServer.safe_start  s    	9JJLLLLL  	8 	8 	8#'> ' -!,#77 	9 	9 	9#'> ' .!-$88		9s    
A5AAAc                 (   d| _         | j        d| j        z  | _        d| _        d}t	          j        dd          r1t          j        dt          j        t          j                  | _        nt          | j
        t          t          f          rY	 |                     | j
                   nB# t          j        $ r*}|d| j
        d|d}t          j        |          |d}~ww xY w| j
        \  }}	 t          j        ||t          j        t          j        d	t          j                  }nO# t          j        $ r= t          j        }| j
        }d
|v rt          j        }|dz   }|t          j        d	d|fg}Y nw xY w|D ]q}|\  }	}
}}}	 |                     |	|
|            nN# t          j        $ r<}|d|d|d}| j        r| j                                         d| _        Y d}~jd}~ww xY w| j        st          j        |          | j                            d           | j                            | j                   t3          j        |           | _        | j                                         d| _        t?          j                    | _         dS )zPrepare server to serving requests.

        It binds a socket's port, setups the socket to ``listen()`` and does
        other preparing things.
        Nz	%s ServerzNo socket could be created
LISTEN_PIDr   z -- (z: r   r   :)r   r   r   r   T)!
_interruptsoftwarer  r  osgetenvfromfdAF_INETSOCK_STREAMr$  r  r#  bytesbind_unix_socketr  getaddrinfo	AF_UNSPEC
AI_PASSIVEgaierrorr   bindr   
settimeoutlistenrequest_queue_sizer   ConnectionManager_connectionsr  r  r   r  r  )r@   r  serrhostr   info	sock_typer  rs   afsocktyper@  
_canonnamesas                 rH   preparezHTTPServer.prepare  s    = '$,6DM *9\4(( '	' -6>6;MNNDKKe55 $	'2%%dn5555< 2 2 2*-##t~~~tttDl3''T12 JD$K)$ 0&6+<  ? K K K"N	 N	$;; &I )F 2I"F$62yIJK  	' 	'693HeZ'IIb(E222E| ' ' '.1cc222ttt<C{ ,))+++"&DKKKKKK	' { 	$,s### 	q!!!42333 (9$?? 	
9;;sC   B+ +C$:%CC$27D* *A	E65E6FG*.2G%%G*c                 x   | j         ry| j        sr	 | j                            | j                   nC# t
          t          f$ r  t          $ r% |                     dt          j
        d           Y nw xY w| j         r| j        r| j        r0| j        rt          j        d           | j        | j        r	| j        dS dS )z1Serve requests, after invoking :func:`prepare()`.zError in HTTPServer.serveTrQ  g?N)r   r  r  runexpiration_intervalrZ  r[  r_  rW  rX  r`  _stopping_for_interruptr  sleeprc   s    rH   servezHTTPServer.serve  s   j 		 		!%%d&>????%z2      /w}"       j 		 		 > 	%.  
3 .  ~ %n$		% 	%% %s   0 =A0/A0c                 V    |                                   |                                  dS )zmRun the server forever.

        It is shortcut for invoking :func:`prepare()` then :func:`serve()`.
        N)r  r  rc   s    rH   r  zHTTPServer.start+  s"     	

r'   c              #      K   |                                   t          j        | j                  }d|_        |                                 	 |V  |                                  dS # |                                  w xY w)z4Context manager for running this server in a thread.)targetTN)r  	threadingThreadr  daemonr  stop)r@   threads     rH   _run_in_threadzHTTPServer._run_in_thread7  so       	!444	LLLIIKKKKKDIIKKKKs   A' 'A=c                 (    | j         o| j        j        S )z>Flag whether it is allowed to add a new keep-alive connection.)r   r  r6  rc   s    rH   r6  z'HTTPServer.can_add_keepalive_connectionC  s     zLd/LLr'   c                 t    | j         r| j                            |           dS |                                 dS )z7Put an idle connection back into the ConnectionManager.N)r   r  putr   r@   r   s     rH   put_connzHTTPServer.put_connH  s<    : 	!!$''''' JJLLLLLr'   r      c                 P   t           j                            d                    |                     t           j                                         |rRt          j                    }t           j                            |           t           j                                         dS dS )zWrite error message to log.

        Args:
            msg (str): error message
            level (int): logging level
            traceback (bool): add traceback to output or not
        z{msg!s}
)r  N)sysstderrr  r   flush
traceback_
format_exc)r@   r  rR  rS  tbliness        rH   rW  zHTTPServer.error_logP  s     	
+++44555
 	 +--GJW%%%J	 	r'   c           	          |                      | j        |||| j        | j        | j                  }|                     || j                  x}| _        |                     |          | _        |S )z.Create (or recreate) the actual socket object.)prepare_socketr  nodelayr   r  bind_socketr  resolve_real_bind_addr)r@   rs  typer@  rM  s        rH   r  zHTTPServer.bind`  sl    ""ND%L$*O	
 
 "--dDNCCCt{44T::r'   c           	         t           r	 t          d          d}	 t          j        | j                   nd# t
          $ r Y nXt          $ r}t          |          }d|vr Y d}~n6d}~wt          $ r&}t          |          }d|vr	d|vrd|vr Y d}~nd}~ww xY w|                     |t          j
        t          j        d| j        | j        | j        	          }	 	 t          j        |                                |           d
}n# t
          $ r d}Y nw xY w	 |                     ||          }n(# t          j        $ r |                                  w xY w|                     |          }	 	 |s@	 t          j        ||           n'# t,          $ r t          j        ||d           Y nw xY wd
}n# t
          $ r Y nw xY w|s!|                     dt2          j                   || _        || _	        |S )z*Create (or recreate) a UNIX socket object.z0AF_UNIX sockets are not supported under Windows.i  zJremove() argument 1 must be encoded string without null bytes, not unicodeNz'unlink: embedded null character in pathzembedded null bytez0argument must be a string without NUL charactersr   )r  rs  r2  r@  r/  r   r  TF)follow_symlinksz(Failed to set socket fs mode permissions)rR  )rr  r3   r  unlinkr  OSError	TypeErrorr#  r.  r  rt  r  r/  r   r  fchmodfilenor0  r  r   r1  lchmodrh  chmodrW  rX  rY  )r@   r  fs_permissionstyp_errerr_msgval_errrM  FS_PERMS_SETs           rH   r  zHTTPServer.bind_unix_socketl  s    	 B   	Idn%%%% 	 	 	   	 	 	'llG="# # 	# # # # #
  		 		 		'llG(/67 7,G;;4;BC C 		 "">(:!Ld.>	 # 
 
	!BIdkkmm^444LL 	! 	! 	! LLL	!	##D)44DD| 	 	 	JJLLL	 //55			C $OIi8888% O O OHYNNNNNNO# 	 	 	D	  	NN:o    
 #s{   5 
B	B
A##B0BB*D DDD. .%E,F0 0F F0 !F*'F0 )F**F0 0
F=<F=c                 4   |d d         \  }}|dk    }| j         t          j        t          j        fvrt	          d          |rt	          d          t          t          d          r-|                     t          j        t          j        d           d S t          t          d          r-|                     t          j        t          j	        d           d S t          r-|                     t          j        t          j        d           d S t          d          )	Nr   r   zCannot reuse a non-IP socketz"Cannot reuse an ephemeral port (0)SO_REUSEPORT_LBr   SO_REUSEPORTz,Current platform does not support port reuse)rs  r  r  r   r3   hasattr
setsockoptrx  rB  rC  rr  SO_REUSEADDRru  )socket_r  r	  r   IS_EPHEMERAL_PORTs        rH   _make_socket_reusablez HTTPServer._make_socket_reusable  s
   rr]
d AI>&.&/!BBB;<<< 	CABBB 6,-- 		v0&2H!LLLLLV^,, 	v0&2EqIIIII 	v0&2EqIIIII%>  r'   c                    t          j         |||          }t          j        |           |dd         \  }	}
|
dk    }|r|                     ||           t          s.|s,	 |                    t           j        t           j        d           |rGt          |t          t          f          s+|                    t           j        t           j        d           ||                    |          }t          t           d          o|t           j        k    o|	dv }|rI	 |                    t           j        t           j        d           n# t$          t           j        f$ r Y nw xY w|S )z%Create and prepare the socket object.Nr   r   rG  r  r   r   )z::z::0z	::0.0.0.0)r  r   prevent_socket_inheritancerI  rr  rE  rx  rF  r$  r#  r  IPPROTO_TCPTCP_NODELAYr  rD  r   r   r   rh  r  )clsr  rs  r2  r@  r/  r   r  rM  r	  r   rH  listening_ipv6s                rH   r.  zHTTPServer.prepare_socket  s    }VT511.t444rr]
d AI 	I%%di%HHH 	G/ 	G	 OOF-v/BAFFF 	G:i#u>> 	GOOF.0BAFFF"##D))D FJ'' 3&/)322 	
  	');Q    #FL1    
 s   +E EEc                 0    |                      |           | S )z#Bind the socket to given interface.)r  rK  s     rH   r0  zHTTPServer.bind_socket  s     	Yr'   c                     |                                  }| j        t          j        t          j        fv r	 |dd         S t          |t                    rt          |          }|S )z/Retrieve actual bind address from bound socket.Nr   )getsocknamers  r  r  r   r$  r  r   rK  s     rH   r1  z!HTTPServer.resolve_real_bind_addr  sk    
 ''))	>NO
 
 

 RaR= i'' 	(YIr'   c                     	 | j                             |           dS # t          j        $ r |                                 Y dS w xY w)z#Process an incoming HTTPConnection.N)r  r"  queueFullr   r#  s     rH   process_connzHTTPServer.process_conn*  sS    	Md#####z 	 	 	JJLLLLLL	s    #AAc                     | j         S )zFlag interrupt of the server.)r  rc   s    rH   r  zHTTPServer.interrupt2  s     r'   c                     | j         t          u S )z8Return whether the server is responding to an interrupt.)r  _STOPPING_FOR_INTERRUPTrc   s    rH   r  z"HTTPServer._stopping_for_interrupt7  s     "999r'   c                     t           | _        t          |t                    r|                     d           t          |t
                    r|                     d           |                                  || _        dS )a  Perform the shutdown of this server and save the exception.

        Typically invoked by a worker thread in
        :py:mod:`~cheroot.workers.threadpool`, the exception is raised
        from the thread running :py:meth:`serve` once :py:meth:`stop`
        has completed.
        z!Keyboard Interrupt: shutting downz SystemExit raised: shutting downN)rZ  r  r$  rZ  rW  r[  r  )r@   r  s     rH   r  zHTTPServer.interrupt<  so     2i!233 	@NN>???i,, 	?NN=>>>		#r'   c                    | j         sdS d| _         | j        )| xj        t          j                    | j        z
  z  c_        d| _        | j                                         t          | dd          }|r^t          | j        t          t          f          s	 |                                dd         \  }}t          j        ||t          j        t          j                  D ]}|\  }}}}}	d}
	 t          j        |||          }
|
                    d           |
                    ||f           |
                                 d# t          j        $ r |
r|
                                 Y w xY wn6# t          j        $ r$}|j        d         t*          j        vr Y d}~nd}~ww xY wt/          |d          r|                                 d| _        | j                                         | j                            | j                   dS )z5Gracefully shutdown a server that is serving forever.NFr  r   g      ?r   r   )r   r  r  r  r  r  r8  r$  r  r#  r  rS  r  r  r  r  r  connectr   r  r   r   r  rD  r  shutdown_timeout)r@   rM  r	  r   rs   r  r  r@  r  _sar  r   s               rH   r  zHTTPServer.stopP  s+   z 	F
'NNty{{T-==>NN   tXt,, #	dnsEl;; **!%!1!1!3!3BQB!7JD$  &1dF$4*    * * @C<HeZ 
* &b(E B BA LL---IItTl333GGIIII%| * * *  * !			** |   wqz)GGG 	 HGGGG8 tW%% 

DK!!!4011111s+   E2 /AE%E.-E.2F%F  F%)r  ro   NFFF)r   r%  Fr   )F);rQ   rR   rS   rT   r  r  r  r  r  r<  r   r  r^  r7  r  r   r   r  r  r   r   r  r/  r   ConnectionClassr   rI  rJ  r  keep_alive_conn_limitr`   r  r  r  r  r  setterr  r  r  r  
contextlibcontextmanagerr  r6  r$  rW  r  r  staticmethodrI  classmethodr.  r0  r1  rW  r  r  r  rK   r'   rH   r   r     sK       JJGJFJ K?H&
   GG $**;*??G.H
 EMMLGN$O9K  !&
 J2A 37;@	! ! ! !F)L )L )LVE E E
 
 
   X6      (9 9 9E' E' E'N% % %*
 
 
 	 	 	 M M XM      
 
 
 
Q Q Qf   \2  2 2 2 [2h   \
   \*     X : : X: $ $ $&32 32 32 32 32r'   r   c                       e Zd ZdZd Zd ZdS )r   zDBase class to interface HTTPServer with other systems, such as WSGI.c                     || _         dS )zuInitialize Gateway instance with request.

        Args:
            req (HTTPRequest): current HTTP request
        N)rb  )r@   rb  s     rH   r`   zGateway.__init__  s     r'   c                     t           )z>Process the current request. Must be overridden in a subclass.)ru  rc   s    rH   r  zGateway.respond  s    !!r'   N)rQ   rR   rS   rT   r`   r  rK   r'   rH   r   r     s8        NN  " " " " "r'   r   z%cheroot.ssl.builtin.BuiltinSSLAdapterz&cheroot.ssl.pyopenssl.pyOpenSSLAdapter)builtin	pyopensslrj  c                    t           |                                          }t          |t                    r|                    d          }||dz   d         }|d|         }	 t
          j        |         }|t                      n;# t          $ r. t          |t                      t                      dg          }Y nw xY w	 t          ||          }n$# t          $ r t          d|d|d          w xY w|S )z/Return an SSL adapter class for the given name.r  r   Nr   'z' object has no attribute ')ssl_adaptersr  r$  r#  rfindr'  modulesKeyError
__import__globalslocalsr8  rh  )nameadapterlast_dot	attr_namemod_pathmods         rH   r   r     s   4::<<(G'3 ==%%HqLMM*	9H9%	B+h'C{jj   	B 	B 	BXwyy&((RDAACCC	B
	c9--GG 	 	 	 .88YYY(  	 Ns   ""B 5B=<B=C !C3)rj  )KrT   r  r  reemail.utilsr9  r  r'  r  rS  r*  rX  platformrU  rc  r  urllib.parser   	functoolsr   r   r   r   r   _compatr   r	   workersr
   rN  r   r   __all__systemrr  r  r   IS_GAEr  r  r  ImportErrorry  rD  r   r   r   rq   r4   r7   r6   r:   r   rr   ASTERISKr   r   compiler?   r   r_  rZ  r=   r-   r   r   r   r   r   r   r   r   r   rn  r   rK   r'   rH   <module>r     s  A AF 
			 				 				      



                           . . . . . . . . . .                   , , , , , , , , X_)+
 ? 
$b	)	)	4	45I	J	J '5v:  N  







   	
 !&SSS MMM   ''&*--  76>** ! 76=))   wv}%% .
  &-2F 	RZ'<)@ A ABB  $)++     ww%% GC( C( C( C( C( C( C( C(L, , , , , , , ,^ ^ ^ ^ ^ ^ ^ ^BW W W W W W W Wt       DP	/ P	/ P	/ P	/ P	/ P	/ P	/ P	/fB B B B B B B BJo
2 o
2 o
2 o
2 o
2 o
2 o
2 o
2d" " " " " " " "& 79      s   *B3 3CC