
    5iL9                       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mZ ddlmZmZ ddl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*nd\  Z'Z(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   )__version__connectionserrors)IS_PPCbton)MakeFileStreamWriter)
threadpool)
ChunkedRFileDropUnderscoreHeaderReaderGatewayHTTPConnectionHTTPRequest
HTTPServerHeaderReaderKnownLengthRFileSizeCheckWrapperget_ssl_adapter_classWindowsSERVER_SOFTWARE zGoogle App Engine/F)NN)NNN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 }d}	 |                                 }|st          d          |t          k    rn|                    t                    st          d          |dd         t          t
          h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hnamelinevkexistings           D/home/kali/Ninja/venv/lib/python3.11/site-packages/cheroot/server.py__call__zHeaderReader.__call__   sm    =E#	>>##D < !:;;;t||==&& C !ABBBBQBxE3<'' JJLL=::eQ//DAqq! = = =$%;<<<=GGII''**%%a(( +++ 99U++ 2

Ha=11AE%LG#	J s   B0 0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         
7 7 7 7r  ( ( ( ( (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                 P    | 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$  s3    ; 	)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.readline6  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linesrD   s        rH   	readlineszSizeCheckWrapper.readlinesQ       }}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.closef      
r'   c                     | S zReturn file iterator.rK   rc   s    rH   __iter__zSizeCheckWrapper.__iter__j      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__n  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__  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.read  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   x  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                 Z   | 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          }n # 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: T   z2Bad chunked transfer coding (expected '\r\n', got ))r   rA   r2   r_   rh   r^   r   rb   r8   r9   	SEMICOLONpopintr3   IOErrorrg   r   r4   repr)r@   rD   
chunk_sizechunkcrlfs        rH   _fetchzChunkedRFile._fetch  s   ; 	Fz""$$3t99$; 	4?T[88(*  
 zz||!!)Q//	!JZ,,JJ 	 	 	<j<<  	
 ??DKF ; 	64?Z7$+EE4555

++3u::%uzq!!4<<d$&)*   <s   %C C"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.readline2  sO    199K	8 D		T));  {  K+**2..K 8"$$ $s4yy 0IDK

33D"&+ijj"9DKK #D3t99$4k B BIDK

33D"&+ijj"9DKK""##L[L11"k+,,73	8r'   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.readlines[  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@   rD   s     rH   read_trailer_lineszChunkedRFile.read_trailer_linesp  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.close  r   r'   )r   rO   r   )rQ   rR   rS   rT   r`   r   rg   r2   r{   r   r   rK   r'   rH   r   r     s        	 	   ) ) )V$ $ $ $@'8 '8 '8 '8R   *  <    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
   | 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          }t7          j        t                    5  |j        }d	d	d	           n# 1 swxY w Y   ||k    p| pt=          ||||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tD                              |          }	|		                    t>                    s
t>          |	z   }	|t4          ur|| _#        || _$        |	| _%        |
| _&        t          | j'        j(        d                   t          | j'        j(        d                   f}|d         |d         k    r|                     d           dS || _)        d tU          ||          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   
contextlibsuppress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  s    z**,,  $ 	54
  :..00L u$$T** 	  !0   5	(4(:(:(<(<(B(B5!(L(L%FC**844 $$%:   uabb!''a00B2ww!||$$%9   us3||$$BF{{$$4,   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	  &2;*$$
 O(< 	 D [J&&? $$%=>>>u --chhs|.D.DEEI9B6GZYE$Z00 ' '!' ' ' ' ' ' ' ' ' ' ' ' ' ' ' 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+$P 
P7!P22P7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(,%^s33}DD$(D! !Z//##$899B NMM$MMM! 		! ! !*$$(,D%% (()<===,0D) 55& >i--@@ ((K(//88# 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.respondE  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_sent  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.write  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 r<| 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\  }}	|                    |t.          z   t*          z   |	z   t,          z              6|                    t,                     | j        j                            t6                              |                     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>  s$    ???e???r'   Nr!  i  Ts   content-length   >   0        r  s   HEAD)r,   r  s
   connection)r*   r  )r*   r  r  ztimeout=r   r   r   s   dates   Date)usegmts   servers   Serverr  )r   r   r   r   r   r   r   rp   r   can_add_keepalive_connectiontimeoutr  r   getattrrA   rg   emailutils
formatdateserver_namer   r6   r4   r:   r   r  r  rr   r?   )
r@   hkeysr   needs_chunkedcan_keepr   protor(  rF   rE   s
             rH   r*  zHTTPRequest.send_headers  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* G&&'EFFF)T_<<O""!4t{244;;LII   % 	+0A 	+  
K;;I1}}
	***%O""K**$*77>>|LL   E!!O""K+22<@@   $++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c c cJb b bH0 0 0.# # # #J     ) ) )\/ \/ \/ \/ \/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& #7)A"6"6"6t7N"O"O2i22243FGG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   statsrI  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  sH   
 -	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!/" &   
 ''-HIII!:. 	 	 	# 	 	 	D  	% 	% 	%$$$$$ 	F 	F 	FK!!Rm "   
 ##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 )NrE  zUThe client sent a plain HTTP request, but this server only speaks HTTPS on this port.r   T)
r   r  _sockAttributeError_socketr   rH  r  r   linger)r@   rc  	resp_sockr  s       rH   r_  zHTTPConnection._handle_no_sslM  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@   rc  responses      rH   rW  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   rk  _close_kernel_socketr  rc   s    rH   r   zHTTPConnection.closen  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NotImplementedErrorrJ  RuntimeError
getsockopt
SOL_SOCKETr   structcalcsizeunpackr  )r@   PEERCRED_STRUCT_DEF
peer_credspiduidgid
socket_errs          rH   rM  zHTTPConnection.get_peer_creds  s     # 	+v~==%G   % 	B  	!// !" 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.rM  )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_RESOLVABLErv  rK  rw  pwdgetpwuidr  pw_namegrpgetgrgidr  gr_name)r@   usergroups      rH   rL  z!HTTPConnection.resolve_peer_creds  sy     % 	%6  
 - 	?   |DM**2T]++3U{r'   c                 4    |                                  \  }}|S )z2Return the username of the connected peer process.rL  )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)	r9  r  shutdown	SHUT_RDWRr   #acceptable_sock_shutdown_exceptionsr  errno$acceptable_sock_shutdown_error_codes)r@   r  es      rH   rp  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_SIZErG  rH  r   rU  rJ  rK  	last_usedr
   r`   rf  rk  r_  rW  r   rM  propertyr  r  r  rL  r  r  rp  rK   r'   rH   r   r     sf       --KKG%H%H% % I.6 H H H H.4 4 4l F  "% % %   &*! *! *!X   X
   X
   X
  0   X
   X
    r'   r   c                      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'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/Fr   Tro   c	                    || _         || _        t          j        | |pd|          | _        |s| j        }|| _        || _        |o|| _        || _	        | 
                                 t          j                    | _        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requestsversionr=  rJ  rK  
reuse_portclear_statsqueueQueue_unservicable_conns)	r@   r  r  
minthreads
maxthreadsr=  rJ  rK  r  s	            rH   r`   zHTTPServer.__init__U  s    . #"-a
 
 
  	',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   rQ  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 )NrQ  ro   runtimer  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  s&    )$4#<" #||~~ r'   AcceptszAccepts/secc                 >    | d                                          z  S )Nr  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  s    Qy\DLLNN%B r'   r  c                 0    t          j        dd           S )Nqsizer9  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   r9  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  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>  s    gdmVT&J&J r'   zSocket ErrorsRequestsc                 |    | d          rdp1t          d | d                                         D             d          S )NrQ  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r   ws     rH   	<genexpr>z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>  s0      HHa:q!!HHHHHHr'   Worker Threadsr   sumvaluesr  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  sM    )$4#<" #HH1-=+>+E+E+G+GHHH  r'   
Bytes Readc                 |    | d          rdp1t          d | d                                         D             d          S )NrQ  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>  s0      JJ<##JJJJJJr'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  sM    !I,&6%>B %JJQ/?-@-G-G-I-IJJJ  r'   Bytes Writtenc                 |    | d          rdp1t          d | d                                         D             d          S )NrQ  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>  s2      MM1#?#A&&MMMMMMr'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  sM    Qy\)9(Ar (MM2B0C0J0J0L0LMMM  r'   	Work Timec                 |    | d          rdp1t          d | d                                         D             d          S )NrQ  ro   c              3   8   K   | ]} |d          |          V  dS )r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>  s0      IIq;""IIIIIIr'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  sM    9%5$=2 $IIA.>,?,F,F,H,HIII  r'   zRead Throughputc                 |    | d          rdp1t          d | d                                         D             d          S )NrQ  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>  s\         $AlOA&&.!K.*;*;*CtD     r'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  sZ    q|+;*C * /07799     r'   zWrite Throughputc                 |    | d          rdp1t          d | d                                         D             d          S )NrQ  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>  s]         'Ao&q))^Q{^A->->-F$G     r'   r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>  sZ    ),<+D" + /07799     r'   r  zCheroot HTTPServer %d)_start_time	_run_timerV  rY  r-   idrc   s   `rH   r  zHTTPServer.clear_stats  su   0
u0
::::0
     0

 q0
 BBBB0
 DDDD0
 LLLL0
 JJJJ0
 Q0
   0
    !0
*   +0
4   50
>     ?0
N  ! !O0
^ b_0

b 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.    #>!~t/?!?@@r'   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.     OOON###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   >   Nr   zzHost 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@   r1  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)startr[  	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socktyperA  
_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)$&%  ? 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                    | j         r| j                                        }|t          u rdS t	          | |          }	 |                    d           nb# t          t          j        f$ r Y jt          $ r>}| j
                            t          |          t          j        d           Y d}~nd}~ww xY wd|_        |                                 | j         dS dS )z(Serve connections we can't handle a 503.Nz503 Service UnavailableTrR  )r   r  r>   _STOPPING_FOR_INTERRUPTr   r   OSErrorr   r]  r`  r   rX  r   rY  ra  rk  r   )r@   r   requestr   s       rH   _serve_unservicablezHTTPServer._serve_unservicableQ  s   j 	+//11D...!$--G''(ABBBBV12        %%HH!-" &        	 DKJJLLL+ j 	 	 	 	 	s   A B2+	B244B--B2c                    t          j        | j                                                   | 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()`.targetzError in HTTPServer.serveTrR  g?N)	threadingThreadr  r  r   r  r
  runexpiration_intervalr[  r\  r`  rX  rY  ra  _stopping_for_interruptr  sleeprc   s    rH   servezHTTPServer.servej  s-   
 	 8999??AAAj 
	 
		!%%d&>????%z2      /!-"       j 
	 
	 > 	%.  
3 .  ~ %n$		% 	%% %s   A =BB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.r  TN)r  r  r  r"  daemonr  stop)r@   threads     rH   _run_in_threadzHTTPServer._run_in_thread  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
  r7  rc   s    rH   r7  z'HTTPServer.can_add_keepalive_connection  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_conn  s<    : 	!!$''''' JJLLLLLr'   r      c                 .   t           j                            |d           t           j                                         |rRt	          j                    }t           j                            |           t           j                                         dS dS )zWrite error message to log.

        :param msg: error message
        :type msg: str

        :param level: logging level
        :type level: int

        :param traceback: add traceback to output or not
        :type traceback: bool
        
N)sysstderrr  flush
traceback_
format_exc)r@   r  rS  rT  tbliness        rH   rX  zHTTPServer.error_log  s     	
C&&&
 	 +--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@   rt  typerA  rN  s        rH   r  zHTTPServer.bind  so    ""N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  rt  r<  rA  r9  r   r  TF)follow_symlinksz(Failed to set socket fs mode permissions)rS  )rs  r3   r  unlinkr  r  	TypeErrorr$  r8  r  ru  r  r9  r   r  fchmodfilenor:  r  r   r;  lchmodri  chmodrX  rY  rZ  )r@   r  fs_permissionstyp_errerr_msgval_errrN  FS_PERMS_SETs           rH   r   zHTTPServer.bind_unix_socket  s    	 B   	Idn%%%% 	 	 	   	 	 	'llG9@GH H H H H H H  	 	 	'llG9HH(77F  	 "">#L( # 
 
	!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        h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)rt  r  r  r   r3   hasattr
setsockoptry  rK  rL  rs  SO_REUSEADDRrv  )socket_r  _hostr   IS_EPHEMERAL_PORTs        rH   _make_socket_reusablez HTTPServer._make_socket_reusable!  s
   mt 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 }|rgt!          j        t$          t           j                  5  |                    t           j        t           j        d           ddd           n# 1 swxY w Y   |S )z%Create and prepare the socket object.Nr   r   rP  r  r   r   >   ::::0	::0.0.0.0)r  r   prevent_socket_inheritancerS  rs  rN  ry  rO  r%  r$  r  IPPROTO_TCPTCP_NODELAYr  rM  r   r   r   ri  r  r   r   )clsr  rt  r<  rA  r9  r   r  rN  r  r   rR  listening_ipv6s                rH   r8  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 	
  	$^V\BB   '&                 s   ;,E33E7:E7c                 0    |                      |           | S )z#Bind the socket to given interface.)r  rU  s     rH   r:  zHTTPServer.bind_socketv  s     	Yr'   c                     |                                  }| j        t          j        t          j        hv r	 |dd         S t          |t                    rt          |          }|S )z/Retrieve actual bind address from bound socket.Nr   )getsocknamert  r  r  r   r%  r  r	   rU  s     rH   r;  z!HTTPServer.resolve_real_bind_addr|  sk    
 ''))	>NO
 
 

 RaR= i'' 	(YIr'   c                     	 | j                             |           dS # t          j        $ r | j                            |           Y dS w xY w)z#Process an incoming HTTPConnection.N)r  r+  r  Fullr  r,  s     rH   process_connzHTTPServer.process_conn  s`    	/Md#####z 	/ 	/ 	/$((......	/s    )A
Ac                     | j         S )zFlag interrupt of the server.)r  rc   s    rH   r  zHTTPServer.interrupt  s     r'   c                     | j         t          u S )z8Return whether the server is responding to an interrupt.)r  r  rc   s    rH   r   z"HTTPServer._stopping_for_interrupt  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)r  r  r%  r[  rX  r\  r&  )r@   r  s     rH   r  zHTTPServer.interrupt  so     2i!233 	@NN>???i,, 	?NN=>>>		#r'   c                 X   | j         sdS d| _         | j                            t                     | 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         t0          j        vr Y d}~nd}~ww xY wt5          |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  r  r
  r&  r9  r%  r  r$  r  r`  r  r  r  r  r  connectr   r  r   r   r  rM  r  shutdown_timeout)r@   rN  r  r   rs   r  r  rA  r  _sar  r   s               rH   r&  zHTTPServer.stop  sG   z 	F
 	 $$%<==='NNdikkD,<<<NN   tXt,, %	dnsEl;; !**!%!1!1!3!3BQB!7JD$  &1(*	    * * @C<HeZ 
* &b(E B BA LL---IItTl333GGIIII%| * * *  * !			*!* |   wqz)GGG 	 HGGGG< tW%% 

DK!!!4011111s+   7F AE%%%FFG F??G)r  ro   NFFF)r   r.  Fr   )F);rQ   rR   rS   rT   r  r  r  r  r  r=  r   r  ri  r8  r  r   r  r  r   r   r  r9  r   ConnectionClassr   rJ  rK  r  keep_alive_conn_limitr`   r  r  r  r  r  setterr  r  r  r"  r  r   contextmanagerr(  r7  r-  rX  r  r   staticmethodrS  classmethodr8  r:  r;  rc  r  r   r&  rK   r'   rH   r   r     sZ       JJGJFJ K?H&
 /  GG )((G.H
 EMMLGN$O9K 
 !&
 J2A "'*1 *1 *1 *1X5L 5L 5LnA A A
 
 
   X6      (9 9 9I' I' I'V  2% % %6
 
 
 	 	 	 M M XM     (   R R Rh   \2  8 8 8 [8t   \
   \*/ / /   X : : X: $ $ $&:2 :2 :2 :2 :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)rc  )r@   rc  s     rH   r`   zGateway.__init__  s     r'   c                     t           )z>Process the current request. Must be overridden in a subclass.)rv  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	pyopensslrt  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$  rfindr1  modulesKeyError
__import__globalslocalsr9  ri  )nameadapterlast_dot	attr_namemod_pathmods         rH   r   r   	  s   4::<<(G'3 ==%%HqLNN+	9H9%	B+h'C{  	B 	B 	BXwyy&((RDAACCC	B
	c9--GG 	 	 	 .7?xxK  	
 Ns   "A> >5B65B6:C !C,)rt  )KrT   r   email.utilsr:  r  rY  r  platformr  rer  r1  r  r  rT  r4  urllib.parser   	functoolsr   r   r   r   r   _compatr   r	   rO  r
   r   workersr   __all__systemrs  r  r   IS_GAEr  r  r  ImportErrorrz  rM  r   r   r   rq   r4   r7   r6   r:   r   rr   ASTERISKr   r   compiler?   r   r`  r  r=   r-   r   r   r   r   r   r   r   r   r   rx  r   rK   r'   rH   <module>r     s  A AF         				  				   				  



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






   	
 !&SSS MMMM'Cf   ''&*--  76>** ! 76=))   wv}%% .
  &-2F 	RZ'<)@ A ABB  $)++    6 ww%% GD( D( D( D( D( D( D( D(N, , , , , , , ,^ ^ ^ ^ ^ ^ ^ ^BW W W W W W W Wt~ ~ ~ ~ ~ ~ ~ ~BY	/ Y	/ Y	/ Y	/ Y	/ Y	/ Y	/ Y	/xC C C C C C C CL|2 |2 |2 |2 |2 |2 |2 |2~" " " " " " " "& 79      s   &B/ /B?>B?