
    qiL9                       S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJrJrJr  SSKJrJr  SSKJrJr  SSKJr  S	r \RB                  " 5       S
:H  r" \RF                  " SS5      RI                  S5      r% \"(       + =(       a    \%(       + r& \&(       a   SSK'r'SSK(r(SSK*r*OSu  r'r(r*\"(       a8  \+" \
S5      (       a*  \+" \
S5      (       d  S\
l,        \+" \
S5      (       d  S\
l-        \+" \
S5      (       d   \(       a  SOS\
l.        Sr/Sr0Sr1Sr2Sr3Sr4Sr5S r6S!r7S"r8\	Rr                  " SRu                  S#\845      5      r;\<" 5       r=/ S$Qr>\+" \S%5      (       d  0 \l?         " S& S'5      r@ " S( S)\@5      rA " S* S+5      rB " S, S-5      rC " S. S/5      rD " S0 S15      rE " S2 S35      rF " S4 S55      rG " S6 S75      rHS8S9S:.rIS<S; jrJg! \) a     Sr&Su  r'r( GN7f = f)=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                   .    \ rS rSrSrSS jrS rS rSrg)	r      zXObject for reading headers from an HTTP request.

Interface and default implementation.
Nc                 R   Uc  0 nSn UR                  5       nU(       d  [        S5      eU[        :X  a   U$ UR                  [        5      (       d  [        S5      eUSS [        [
        1;   a  UR                  5       nO< UR                  [        S5      u  peUR                  5       nU R                  U5      nUnU R                  W5      (       d  M  U[        ;   a*  UR                  U5      nU(       a  SR                  Xu45      nXRU'   GM  ! [         a    [        S5      ef = f)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.
N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           C/home/kali/flask_env/lib/python3.13/site-packages/cheroot/server.py__call__HeaderReader.__call__   s    =E>>#D !:;;t|: 9 ==&& !ABBBQxE3<' JJL=::eQ/DA GGI''*%%a((++ 99U+

H=1A%LG , " =$%;<<=s   D D&c                     g)NT rA   key_names     rI   r=   HeaderReader._allow_header  s    r'   c                 >    UR                  5       R                  5       $ N)r9   titlerN   s     rI   r<   HeaderReader._transform_key
  s    ~~%%''r'   rM   rR   )	__name__
__module____qualname____firstlineno____doc__rJ   r=   r<   __static_attributes__rM   r'   rI   r   r      s    
7r(r'   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )r   i  zDCustom HeaderReader to exclude any headers with underscores in them.c                 F   > [         [        U ]  U5      nU=(       a    SU;  $ )N_)superr   r=   )rA   rO   orig	__class__s      rI   r=   (DropUnderscoreHeaderReader._allow_header  s%    /DXN+8++r'   rM   )rU   rV   rW   rX   rY   r=   rZ   __classcell__)r`   s   @rI   r   r     s    N, ,r'   r   c                   X    \ rS rSrSrS rS rSS jrSS jrSS jr	S	 r
S
 rS r\rSrg)r   i  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                 *    Xl         X l        SU l        g)z%Initialize SizeCheckWrapper instance.r   N)rB   maxlen
bytes_read)rA   rB   re   s      rI   __init__SizeCheckWrapper.__init__  s    
r'   c                 |    U R                   (       a+  U R                  U R                   :  a  [        R                  eg g rR   )re   rf   r   MaxSizeExceededrA   s    rI   _check_lengthSizeCheckWrapper._check_length$  s+    ;;4??T[[8((( 9;r'   Nc                     U R                   R                  U5      nU =R                  [        U5      -  sl        U R	                  5         U$ )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
)rB   readrf   lenrl   rA   sizedatas      rI   rp   SizeCheckWrapper.read(  s9     zzt$3t9$r'   c                    UbK  U R                   R                  U5      nU =R                  [        U5      -  sl        U R	                  5         U$ / n U R                   R                  S5      nU =R                  [        U5      -  sl        U R	                  5         UR                  U5        [        U5      S:  d  USS [        :X  a  [        R                  U5      $ M  )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
N   )	rB   r3   rf   rq   rl   appendLFEMPTYr@   )rA   rs   rt   ress       rI   r3   SizeCheckWrapper.readline6  s     ::&&t,DOOs4y(O K ::&&s+DOOs4y(O JJt4y3$rs)r/zz#& r'   c                     Sn/ nU R                  U5      nU(       aK  UR                  U5        U[        U5      -  nSUs=:  a	  U::  a    U$   U R                  U5      nU(       a  MK  U$ 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   r3   rz   rq   rA   sizehinttotallinesrE   s        rI   	readlinesSizeCheckWrapper.readlinesQ  o     }}X&LLSYE8$u$ %==*D d r'   c                 8    U R                   R                  5         gz*Release resources allocated for ``rfile``.NrB   closerk   s    rI   r   SizeCheckWrapper.closef      

r'   c                     U $ zReturn file iterator.rM   rk   s    rI   __iter__SizeCheckWrapper.__iter__j      r'   c                     [        U R                  5      nU =R                  [        U5      -  sl        U R	                  5         U$ zGenerate next file chunk.)nextrB   rf   rq   rl   rA   rt   s     rI   __next__SizeCheckWrapper.__next__n  s3    DJJ3t9$r'   )rf   re   rB   rR   r   )rU   rV   rW   rX   rY   rg   rl   rp   r3   r   r   r   r   r   rZ   rM   r'   rI   r   r     s6    )'6* Dr'   r   c                   R    \ rS rSrSrS rSS jrSS jrSS jrS r	S	 r
S
 r\rSrg)r   ix  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                     Xl         X l        g)z%Initialize KnownLengthRFile instance.N)rB   	remaining)rA   rB   content_lengths      rI   rg   KnownLengthRFile.__init__  s    
'r'   Nc                     U R                   S:X  a  gUc  U R                   nO[        XR                   5      nU R                  R                  U5      nU =R                   [	        U5      -  sl         U$ )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   minrB   rp   rq   rr   s      rI   rp   KnownLengthRFile.read  sX     >>Q<>>Dt^^,Dzzt$#d)#r'   c                     U R                   S:X  a  gUc  U R                   nO[        XR                   5      nU R                  R                  U5      nU =R                   [	        U5      -  sl         U$ )rw   r   r'   )r   r   rB   r3   rq   rr   s      rI   r3   KnownLengthRFile.readline  sZ     >>Q<>>Dt^^,Dzz""4(#d)#r'   c                     Sn/ nU R                  U5      nU(       aK  UR                  U5        U[        U5      -  nSUs=:  a	  U::  a    U$   U R                  U5      nU(       a  MK  U$ r   r   r   s        rI   r   KnownLengthRFile.readlines  r   r'   c                 8    U R                   R                  5         gr   r   rk   s    rI   r   KnownLengthRFile.close  r   r'   c                     U $ r   rM   rk   s    rI   r   KnownLengthRFile.__iter__  r   r'   c                 l    [        U R                  5      nU =R                  [        U5      -  sl        U$ r   )r   rB   r   rq   r   s     rI   r   KnownLengthRFile.__next__  s'    DJJ#d)#r'   )r   rB   rR   r   )rU   rV   rW   rX   rY   rg   rp   r3   r   r   r   r   r   rZ   rM   r'   rI   r   r   x  s1    (
((* Dr'   r   c                   R    \ rS rSrSrSS jrS rSS jrSS jrSS jr	S	 r
S
 rSrg)r   i  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                 Z    Xl         X l        SU l        [        U l        X0l        SU l        g)z!Initialize ChunkedRFile instance.r   FN)rB   re   rf   r|   bufferbufsizeclosed)rA   rB   re   r   s       rI   rg   ChunkedRFile.__init__  s&    
r'   c                    U R                   (       a  g U R                  R                  5       nU =R                  [	        U5      -  sl        U R
                  (       a;  U R                  U R
                  :  a!  [        R                  " SU R
                  5      eUR                  5       R                  [        S5      n UR                  S5      n[        US5      nUS::  a  SU l         g U R
                  (       a(  U R                  U-   U R
                  :  a  [        S5      eU R                  R                  U5      nU =R                  [	        U5      -  sl        U =R                   U-  sl        U R                  R                  S5      nU["        :w  a  [        S[%        U5      -   S	-   5      eg ! [         a    [        SW< 35      ef = f)
NRequest Entity Too Larger   r      zBad chunked transfer size: T   z2Bad chunked transfer coding (expected '\r\n', got ))r   rB   r3   rf   rq   re   r   rj   r9   r:   	SEMICOLONpopintr4   IOErrorrp   r   r5   repr)rA   rE   
chunk_sizechunkcrlfs        rI   _fetchChunkedRFile._fetch  su   ;;zz""$3t9$;;4??T[[8((* 
 zz|!!)Q/	!JZ,J ?DK ;;4??Z7$++E455


+3u:%uzzq!4<d$&)*  '  	-j^< 	s   <F. .GNc                 d   [         nUS:X  a  U$  U(       a  [        U5      U:  a  U$ U R                  (       d#  U R                  5         U R                  (       d  U$ U(       a4  U[        U5      -
  nX R                  SU -  nU R                  US U l        OX R                  -  n[         U l        M  )ro   r   N)r|   rq   r   r   )rA   rs   rt   r   s       rI   rp   ChunkedRFile.read  s     19KD	T);;{{K 3t9,	JY//"kk)*5##! r'   c                    [         nUS:X  a  U$  U(       a  [        U5      U:  a  U$ U R                  (       d#  U R                  5         U R                  (       d  U$ U R                  R	                  [
        5      nU(       ax  US:X  a4  U[        U5      -
  nX R                  SU -  nU R                  US U l        O[        U[        U5      -
  U5      nX R                  SU -  nU R                  US U l        OEUS:X  a  X R                  -  n[         U l        O%X R                  SU -  nU R                  US U l        GM2  )rw   r   ry   N)r|   rq   r   r   findr{   r   )rA   rs   rt   newline_posr   s        rI   r3   ChunkedRFile.readline2  s    19KD	T);;{{K++**2.K"$ $s4y 0IKK
33D"&++ij"9DK #D3t9$4k BIKK
33D"&++ij"9DK"##L[11"kk+,73 r'   c                     Sn/ nU R                  U5      nU(       aK  UR                  U5        U[        U5      -  nSUs=:  a	  U::  a    U$   U R                  U5      nU(       a  MK  U$ r   r   r   s        rI   r   ChunkedRFile.readlines[  r   r'   c              #     #    U R                   (       d  [        S5      e U R                  R                  5       nU(       d  [        S5      eU =R                  [        U5      -  sl        U R                  (       a%  U R                  U R                  :  a  [        S5      eU[        :X  a  gUR                  [        5      (       d  [        S5      eUv   M  7f)zPRead HTTP headers and yield them.

:yields: CRLF separated lines
:ytype: bytes

z:Cannot read trailers until the request body has been read.r1   r   r2   N)
r   r4   rB   r3   rf   rq   re   r   r5   r6   )rA   rE   s     rI   read_trailer_linesChunkedRFile.read_trailer_linesp  s      {{L  ::&&(D !:;;OOs4y(O{{t<899t|==&& !ABBJ! s   CCc                 8    U R                   R                  5         gr   r   rk   s    rI   r   ChunkedRFile.close  r   r'   )r   r   rf   r   re   rB   )i    rR   r   )rU   rV   rW   rX   rY   rg   r   rp   r3   r   r   r   rZ   rM   r'   rI   r   r     s-    	)V$@'8R*<r'   r   c                       \ rS rSrSrSr Sr 0 r / r Sr	 Sr
 Sr \" 5       r SS jrS rS rS rS	 rSS
 jrS rS rS rSrg)r   i  zjAn HTTP Request (and response).

A single HTTP connection may consist of multiple request/response pairs.
NFc                 Z   Xl         X l        SU l        SU l        SU l        U R                   R
                  b  SU l        SU l        0 U l        SU l        / U l	        SU l
        U R                  R                  U l        SU l        U R                  R                  U l        X0l        X@l        g)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_headersr`   close_connectionchunked_readchunked_write
proxy_modestrict_mode)rA   r   r   r   r   s        rI   rg   HTTPRequest.__init__  s     	
$;;""."DK!+! $ ? ?!!^^99$&r'   c                    [        U R                  R                  U R                  R                  5      U l         U R                  5       nU(       d  g  U R                  5       nU(       d  g SU l
        g! [        R                   a    U R                  SS5         gf = f! [        R                   a    U R                  SS5         gf = f)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   rB   r   max_request_header_sizeread_request_liner   rj   simple_responseread_request_headersr   )rA   successs     rI   parse_requestHTTPRequest.parse_request  s    %IIOOKK//

	,,.G  	//1G   
1 %% 	  *!
 	 %% 	  .!
 	s#   A6 B" 6&BB"&C
Cc                 
   U R                   R                  5       nSU l        U(       d  gU[        :X  a"  U R                   R                  5       nU(       d  gUR	                  [        5      (       d  U R                  SS5        g UR                  5       R                  [        S5      u  p#nUR                  S5      (       d  U R                  SS5        gUSS	 R                  S
S5      n[        U5      S:w  a  U R                  SS5        g[        [        [        U5      5      nUS:  a  U R                  SS5        g X0l        UR#                  5       U l        U R&                  (       a$  X R$                  :w  a  SnU R                  SU5        g [(        R*                  R-                  U5      u  pxpnU=(       d    UnU R$                  S:X  a  U R0                  (       a	  U(       a  UOU	n	GOU R$                  S:X  a  U R0                  (       d  U R                  S5        g[(        R*                  R-                  SR3                  SU45      5      nUu  pnnn[4        n[6        R8                  " [        5         UR:                  nS	S	S	5        X:g  =(       d    U(       + =(       d    [=        UUUU45      nU(       a  U R                  SS5        gU=p[4        =n=pGO(U R&                  =(       a    U R0                  (       + =(       a    UnU(       a   U R                  SS5        gU R&                  =(       a(    UR                  [>        5      (       + =(       a    U(       + nU(       a   SnU R                  SU5        gU(       a  U R                  SS5        gU	c  U R                  SS5        g [@        R                  U	5       Vs/ s H"  n[(        R*                  RC                  U5      PM$     nn[F        R3                  U5      n	U	R                  [>        5      (       d	  [>        U	-   n	U[4        La  Xpl$        Xl%        Xl&        Xl'        [        U RP                  RR                  S   5      [        U RP                  RR                  S   5      4nUS   US   :w  a  U R                  S5        gX@l*        S[W        UU5      -  U l,        g! [        [        4 a    U R                  SS5         gf = f! [.         a    U R                  SS5         gf = f! , (       d  f       GN= fs  snf ! [         a)  nU R                  SURD                  S   5         S	nAgS	nAff = f) 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 Requestr2   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.r      z
HTTP/%s.%s)-rB   r3   r   r5   r6   r   r9   r:   r7   
startswithrq   tuplemapr   r4   
IndexErroruriuppermethodr   urllibparseurlsplitUnicodeErrorr   r@   r|   
contextlibsuppressportanyFORWARD_SLASHQUOTED_SLASH_REGEXunquote_to_bytesargsQUOTED_SLASHr   	authoritypathqsr   protocolrequest_protocolr   r   )rA   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xatomsexsps                             rI   r   HTTPRequest.read_request_line  s    zz**,  $4
  ::..0L$$T**  !0 	(4(:(:(<(B(B5!(L%F**844$$%: ab!''a0B2w!|$$%9 s3|$BF{$$4,   lln++ 5A    !2D9	4:LL4I4I#4N1Ft
  &2;;*$
 OO(<  	  [[J&??$$%=> --chhs|.DEI9B6GYE$$Z0! 1 ! 999Y78 
 $$%8
 ))I%**F*R(    )')(  
 # C$$%H     -}55-,, 
  >2 
 $$%6=$$%7 |$$%2 	
 055d;; LL11!4;    $$U+D}-- 4'D K"	  %%a()3t{{/C/CA/F+GGa5BqE>  !AB ,!-B!;O J' 	  !24LM	&  	  !24KL	2 10b  $$%6
Csg   AS 6S 1S #S+ 5T+T$ )T+T$ "S('S(+T
	T

TT$ $
U.UUc                     U R                  U R                  U R                  5        U R                  R                  n [        U R                  R                  SS5      5      nU(       a  X2:  a  U R	                  SS5        gU R                  S	:X  a(  U R                  R                  S
S5      S:X  a  SU l        O'U R                  R                  S
S5      S:w  a  SU l        SnU R                  S	:X  au  U R                  R                  S5      nU(       aS  UR                  S5       Vs/ s H7  oUR                  5       (       d  M  UR                  5       R                  5       PM9     nnSU l        U(       a0  U H*  nUS:X  a	  SU l        M  U R	                  S5        SU l          g   U R                  R                  SS5      S:X  al  SR!                  U R                  R"                  R%                  S5      [&        S[(        [(        45      n U R*                  R,                  R/                  U5        gg! [         a)  nU R	                  SUR
                  S   5         SnAgSnAff = f! [         a    U R	                  SS5         gf = fs  snf ! [0        R2                   a,  nUR
                  S   [4        R6                  ;  a  e  SnAgSnAff = f)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,      ,   chunkedz501 Unimplementedr+   s   100-continueasciis   100 Continue)header_readerrB   r   r4   r   r  r   max_request_body_sizer   r?   r   r   r:   r9   lowerr   r@   r  encoder7   r5   r   wfilewritesocketerrorr   socket_errors_to_ignore)rA   r  mrbsclter  encmsgs           rI   r    HTTPRequest.read_request_headers  sr   	tzz4>>:
 {{00	T^^''(91=>B BI  .!
  !!Z/~~!!-5A(,%^^s3}D$(D! !!Z/##$89B13$MA779'aggioo'M!*$(,D% (()<=,0D)  6 >>i-@ ((KK((//8#C		%%c* o  	  !2BGGAJ?	  	  !2 	: N^ << 771:V%C%CC DsL   &H4 %I* )J"J%J 4
I'>I""I'*J	J	K%"KKc                    U R                   R                  nU R                  (       a&  [        U R                  R
                  U5      U l        Oz[        U R                  R                  SS5      5      nU(       a)  X:  a$  U R                  (       d  U R                  SS5        g[        U R                  R
                  U5      U l        U R                   R                  U 5      R                  5         U R                  =(       a    U R                  5         U R                   (       a&  U R                  R"                  R%                  S5        gg)z/Call the gateway and write its iterable output.r  r   r   r  Ns   0

)r   r'  r   r   r   rB   r   r   r?   r   r   r   gatewayrespondr   ensure_headers_sentr   r*  r+  )rA   r/  r0  s      rI   r7  HTTPRequest.respondE  s    {{00%diioot<DJT^^''(91=>B	((((61
 )$))//2>DJD!))+

1t//1IIOO!!,/ r'   c                    [        U5      nU R                  R                  < SU< S3nS[        U5      -  nSnUR	                  S5      UR	                  S5      UR	                  S5      /nUSS S;   a+  S	U l        U R                  S
:X  a  UR                  S5        OSnUR                  [        5        U(       a7  [        U[         5      (       a  UR	                  S5      nUR                  U5         U R                  R                  R                  [        R                  U5      5        g! [        R                    a,  nUR"                  S   [$        R&                  ;  a  e  SnAgSnAff = f)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  rq   r)  r   r   rz   r5   
isinstancer   r*  r+  r|   r@   r,  r-  r  r   r.  )rA   r   r3  proto_statusr   content_typebufr  s           rI   r   HTTPRequest.simple_response\  s*   V&*kk&:&:FC1CH<5-!!,/-
 "1:'$(D!%%3 

34 +

4#s##jj.JJsO	IIOO!!%**S/2|| 	wwqz!?!?? @	s   48D- -E-"E((E-c                 V    U R                   (       d  SU l         U R                  5         gg)z:Ensure headers are sent to the client if not already sent.TN)r   send_headersrk   s    rI   r8  HTTPRequest.ensure_headers_sent  s$       $D !r'   c                 X   U R                   (       at  U(       am  [        [        U5      5      SS R                  S5      nU[        U[        /nU R
                  R                  R                  [        R                  U5      5        gU R
                  R                  R                  U5        g)z$Write unbuffered data to the client.r   Nr%  )
r   hexrq   r)  r5   r   r*  r+  r|   r@   )rA   r   chunk_size_hexrD  s       rI   r+  HTTPRequest.write  sn    % U_QR077@N!45CIIOO!!%**S/2IIOO!!%(r'   c                    U R                    VVs/ s H  u  pUR                  5       PM     nnn[        U R                  SS 5      nUS:X  a  SU l        OiSU;  ac  US:  d  US;   a  OVU R
                  S:H  =(       a    U R                  S	:g  nU(       a#  SU l        U R                   R                  S
5        OSU l        U R                  (       d"  U R                  R                  nU(       + U l        SU;  ai  U R
                  S:X  a-  U R                  (       a  U R                   R                  S5        O,U R                  (       d  U R                   R                  S5        SU R                   ;   aC  U R                   R                  SSU R                  R                   3R                  S5      45        U R                  (       dI  U R                  (       d8  [        U R                  SS5      nUS:  a  U R                  R!                  U5        SU;  aG  U R                   R                  S["        R$                  R'                  SS9R                  S5      45        SU;  a@  U R                   R                  SU R                  R(                  R                  S5      45        U R                  R*                  R                  S5      nU[,        -   U R                  -   [.        -   /n	U R                    H.  u  pU	R                  U
[0        -   [,        -   U-   [.        -   5        M0     U	R                  [.        5        U R2                  R4                  R7                  [8        R;                  U	5      5        gs  snnf )zAssert, process, and send the HTTP response message-headers.

You must set ``self.status``, and :py:attr:`self.outheaders
<HTTPRequest.outheaders>` before calling this.
Nr=  i  Ts   content-lengthr/   >   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   r   rz   r   can_add_keepalive_connectiontimeoutr)  r   getattrrB   rp   emailutils
formatdateserver_namer  r7   r5   r;   r   r*  r+  r|   r@   )rA   keyvaluehkeysr   needs_chunkedcan_keepr   protorD  rG   rF   s               rI   rG  HTTPRequest.send_headers  s    04??T[[!_%S=$(D!e+ |v8 **j8 /w.  !)-D&OO**+MN -1D) $${{??H(0LD!%%%3((OO**+DE**&&'EF)T__<OO""!t{{2234;;LI %%0A0A  

K;I1}

	*%OO""KK**$*7>>|L E!OO""KK++22<@ $$++G4u}t{{*T12OODAJJq5y5(1,t34 $

4		ejjo.m @s   M/)r  r   r   r   r   r   r   r   r  r   r  r   r  r   rB   r   r   r   r   r   r   r   )FT)r   )rU   rV   rW   rX   rY   r   r   r   r   r   r   r   r   r&  rg   r   r   r   r7  r   r8  r+  rG  rZ   rM   r'   rI   r   r     s    
 F@DDI$J;E@  M< !NM'B DcJbH0.#J )\/r'   r   c                       \ rS rSrSrSrSrSr\R                  r
\R                  r\rSrSrSr\4S jrS rSrS rS rS	 rS
 r\S 5       r\S 5       r\S 5       rS r\S 5       r\S 5       rS r Sr!g)r   i  z#An HTTP connection (active socket).NFc                 r   Xl         X l        U" USU R                  5      U l        U" USU R                  5      U l        SU l        U R                   R                  U l        U R                   R                  U l        [        SS9" U R                  5      U l
        [        SS9" U R                  5      U l        g)a  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,  rbufsizerB   wbufsizer*  requests_seenpeercreds_enabledpeercreds_resolve_enabledr   resolve_peer_credsget_peer_creds)rA   r   sockmakefiles       rI   rg   HTTPConnection.__init__  s     dD$--8
dD$--8
!%!>!>)-)N)N& #,A"6t7N7N"O'243F3FGr'   c                    Sn U R                  U R                  U 5      nUR                  5         U R                  R                  S   (       a  U =R                  S-  sl        UR
                  (       d  gSnUR                  5         UR                  (       d  g g! [        R                   a  nUR                  S   nSnXE;   a6  U(       a  W(       a#  UR                  (       a  U R                  WS5         SnAgU[        R                  ;  aG  U R                  R                  S[!        U5      -  ["        R$                  SS	9  U R                  WS
5         SnAgSnAf[&        [(        4 a    e [        R*                   a     g[        R,                   a    U R/                  W5         g[0         aN  nU R                  R                  [!        U5      ["        R2                  SS	9  U R                  WS
5         SnAgSnAff = f)zbRead 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   statsrg  r   r7  r   r,  r-  r  r   _conditional_errorr   r.  	error_logr   loggingWARNINGKeyboardInterrupt
SystemExitFatalSSLAlert
NoSSLError_handle_no_ssl	ExceptionERROR)rA   request_seenreqr  errnumtimeout_errss         rI   communicateHTTPConnection.communicate  s   
 -	F**4;;=C{{  +""a'"99 LKKM'' (B ? || 	JWWQZFFL%
 %##2E2E++C1FG* ) v===%%%V4!//" & 
 ''-HI  ":. 	## 	     	%$   	FKK!!Rmm " 
 ##C)DEE	Fs?   A0B 5#B H/AE;AE'H$H*	H3AG<<Hc                    U(       a  UR                   (       a  g  U R                  R                  n[        USU R                  5      U l        SnUR                  SU5        SU l	        g ! [         a    U R                  R                  n NZf = f)Nrc  zUThe client sent a plain HTTP request, but this server only speaks HTTPS on this port.r   T)
r   r,  _sockAttributeError_socketr   rf  r*  r   linger)rA   r  	resp_sockr3  s       rI   r~  HTTPConnection._handle_no_sslM  s~    c&&	,))I ")T4==A
: 	 	-s3  	,++I	,s   A) ) BBc                     U(       a  UR                   (       a  g UR                  U5        g! [        R                   a     g[        R                   a    U R                  U5         gf = f)z^Respond with an error.

Don't bother writing if a response
has already started being written.
N)r   r   r   r|  r}  r~  )rA   r  responses      rI   rv  !HTTPConnection._conditional_error^  sY     c&&	%)## 	   	%$	%s   - A*$A*)A*c                     U R                   R                  5         U R                  (       d+  U R                  5         U R                  R                  5         gg)z,Close the socket underlying this connection.N)rB   r   r  _close_kernel_socketr,  rk   s    rI   r   HTTPConnection.closen  s<    

{{%%' KK r'   c                    Sn[         (       d(  U R                  R                  [        R                  :w  a  [	        S5      eU R
                  (       d  [        S5      e U R                  R                  [        R                  [        R                  [        R                  " U5      5      n[        R                  " X5      u  p4nX4U4$ ! [        R                   a  n [        UeSnAff = f)ab  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NotImplementedErrorrh  RuntimeError
getsockopt
SOL_SOCKETr   structcalcsizeunpackr-  )rA   PEERCRED_STRUCT_DEF
peer_credspiduidgid
socket_errs          rI   rk  HTTPConnection.get_peer_creds  s     #:++v~~=%G  %%B 	!// !!"" 34J" #MM*=JMCcS=  || 	/ J.	/s   AC C)C$$C)c                 .    U R                  5       u  n  nU$ )z,Return the id of the connected peer process.rk  )rA   r  r]   s      rI   peer_pidHTTPConnection.peer_pid  s     '')	Q
r'   c                 ,    U R                  5       u  pnU$ )z1Return the user id of the connected peer process.r  )rA   r]   r  s      rI   peer_uidHTTPConnection.peer_uid  s     '')	
r'   c                 ,    U R                  5       u    pU$ )z2Return the group id of the connected peer process.r  )rA   r]   r  s      rI   peer_gidHTTPConnection.peer_gid  s     '')	1
r'   c                    [         (       d  [        S5      eU R                  (       d  [        S5      e[        R
                  " U R                  5      R                  n[        R                  " U R                  5      R                  nX4$ )zLook 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_RESOLVABLEr  ri  r  pwdgetpwuidr  pw_namegrpgetgrgidr  gr_name)rA   usergroups      rI   rj  !HTTPConnection.resolve_peer_creds  sq     %$%6 
 --?  ||DMM*22T]]+33{r'   c                 *    U R                  5       u  pU$ )z2Return the username of the connected peer process.rj  )rA   r  r]   s      rI   	peer_userHTTPConnection.peer_user  s     ))+r'   c                 *    U R                  5       u  pU$ )z/Return the group of the connected peer process.r  )rA   r]   r  s      rI   
peer_groupHTTPConnection.peer_group  s     **,r'   c                 2   [        U R                  SU R                  R                  5      n U" [        R                  5        g! [        R
                   a     g[        R                   a)  nUR                  [        R                  ;  a  e  SnAgSnAff = f)z0Terminate the connection at the transport level.sock_shutdownN)	rT  r,  shutdown	SHUT_RDWRr   #acceptable_sock_shutdown_exceptionsr-  errno$acceptable_sock_shutdown_error_codes)rA   r  es      rI   r  #HTTPConnection._close_kernel_socket  sx     KKKK  
	V%%&99 	|| 	wwfIII J	s   A BB-BB)
rk  r  rh  ri  rg  rj  rB   r   r,  r*  )"rU   rV   rW   rX   rY   remote_addrremote_portssl_envioDEFAULT_BUFFER_SIZEre  rf  r   rt  rh  ri  	last_usedr
   rg   r  r  r~  rv  r   rk  propertyr  r  r  rj  r  r  r  rZ   rM   r'   rI   r   r     s    -KKG%%H%%H% % I.6 H.4l F"% &*!X  
  
  
0  
  
r'   r   c                   
   \ rS rSrSrSrSrSr Sr Sr	 Sr
 Sr Sr Sr Sr Sr S	\< 3r Sr S
r Sr Sr Sr \r Sr S
r S
r S
r Sr       S(S jrS rS r S r!\"S 5       r#\#RH                  S 5       r#S r%S r&S r'S r(S r)\*RV                  S 5       r,\"S 5       r-S r.S)S jr/S*S jr0S r1\2S 5       r3\4 S+S j5       r5\2S  5       r6\2S! 5       r7S" r8\"S# 5       r9\"S$ 5       r:\9RH                  S% 5       r9S& r;S'r<g),r   i  zAn HTTP server.z	127.0.0.1Nr   r   
   g      ?zCheroot/Fr   Tc	                 "   Xl         X l        [        R                  " U U=(       d    SUS9U l        U(       d  U R
                  nXPl        X`l        U=(       a    UU l        Xl	        U R                  5         [        R                  " 5       U l        g)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_addrr6  r   
ThreadPoolrequestsversionrX  rh  ri  
reuse_portclear_statsqueueQueue_unservicable_conns)	rA   r  r6  
minthreads
maxthreadsrX  rh  ri  r  s	            rI   rg   HTTPServer.__init__U  sy    . #"--a
 ,,K&!2%;*; 	& %#(;;= r'   c                   ^  ST l         ST l        0 SS_SU 4S j_SU 4S j_S	S_S
U 4S j_SU 4S j_SU 4S j_SU 4S j_SS_SS _SS _SS _SS _SS _SS _S0 _T l        T R                  [        R                  S [        T 5      -  '   g)!zReset server stat counters..Nr   rp  FzBind Addressc                 .   > [        TR                  5      $ rR   )r   r  srA   s    rI   <lambda>(HTTPServer.clear_stats.<locals>.<lambda>  s    d4>>&:r'   zRun timec                 X   > U S   (       + =(       a    S=(       d    TR                  5       $ )Nrp  ry   runtimer  s    rI   r  r    s$    )$4#<" #||~#r'   AcceptszAccepts/secc                 0   > U S   TR                  5       -  $ )Nr  r  r  s    rI   r  r    s    Qy\DLLN%Br'   r  c                 2   > [        TR                  SS 5      $ )NqsizerT  r  r  s    rI   r  r    s    wt}}gtDr'   Threadsc                 D   > [        [        TR                  S/ 5      5      $ )N_threads)rq   rT  r  r  s    rI   r  r    s    WT]]J%K!Lr'   zThreads Idlec                 2   > [        TR                  SS 5      $ )Nidler  r  s    rI   r  r    s    gdmmVT&Jr'   zSocket ErrorsRequestsc                 ~    U S   (       + =(       a    S=(       d$    [        S U S   R                  5        5       S5      $ )Nrp  ry   c              3   6   #    U  H  oS    " U5      v   M     g7f)r  NrM   .0ws     rI   	<genexpr>;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>  s     H+Ga:q!!+G   Worker Threadsr   sumvaluesr  s    rI   r  r    s<    )$4#<" #H1-=+>+E+E+GH#r'   
Bytes Readc                 ~    U S   (       + =(       a    S=(       d$    [        S U S   R                  5        5       S5      $ )Nrp  ry   c              3   6   #    U  H  oS    " U5      v   M     g7f)r  NrM   r  s     rI   r  r    s     J-I<##-Ir  r  r   r   r  s    rI   r  r    s<    !I,&6%>B %JQ/?-@-G-G-IJ%r'   Bytes Writtenc                 ~    U S   (       + =(       a    S=(       d$    [        S U S   R                  5        5       S5      $ )Nrp  ry   c              3   6   #    U  H  oS    " U5      v   M     g7f)r  NrM   r  s     rI   r  r    s     M0L1?#A&&0Lr  r  r   r   r  s    rI   r  r    s<    Qy\)9(Ar (M2B0C0J0J0LM(r'   	Work Timec                 ~    U S   (       + =(       a    S=(       d$    [        S U S   R                  5        5       S5      $ )Nrp  ry   c              3   6   #    U  H  oS    " U5      v   M     g7f)r
  NrM   r  s     rI   r  r    s     I,Hq;"",Hr  r  r   r   r  s    rI   r  r    s<    9%5$=2 $IA.>,?,F,F,HI$r'   zRead Throughputc                 ~    U S   (       + =(       a    S=(       d$    [        S U S   R                  5        5       S5      $ )Nrp  ry   c              3   b   #    U  H%  nUS    " U5      US   " U5      =(       d    S-  v   M'     g7f)r  r
  ư>NrM   r  s     rI   r  r    s3      9 lOA&!K.*;*CtD9   -/r  r   r   r  s    rI   r  r    sC    q|+;*C */0779 *r'   zWrite Throughputc                 ~    U S   (       + =(       a    S=(       d$    [        S U S   R                  5        5       S5      $ )Nrp  ry   c              3   b   #    U  H%  nUS    " U5      US   " U5      =(       d    S-  v   M'     g7f)r  r
  r  NrM   r  s     rI   r  r    s4      9 o&q)Q{^A->-F$G9r  r  r   r   r  s    rI   r  r    sC    ),<+D" +/0779 +r'   r  zCheroot HTTPServer %d)_start_time	_run_timeru  rx  r-   idrk   s   `rI   r  HTTPServer.clear_stats  s   0
u0
:0
  0

 q0
 B0
 D0
 L0
 J0
 Q0
  0
   !0
*  +0
4  50
>   ?0
N  !O0
^ b_0

b BF2RX=>r'   c                     U R                   c  U R                  $ U R                  [        R                  " 5       U R                   -
  -   $ )zReturn server uptime.)r  r  timerk   s    rI   r  HTTPServer.runtime  s8    #>>!~~t/?/?!?@@r'   c                 n    U R                   < SU R                  R                  < SU R                  < S3$ )z1Render Server instance representing bind address..(r   )rV   r`   rU   r  rk   s    rI   __str__HTTPServer.__str__  s)     OONN##NN
 	
r'   c                     U R                   $ )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_addrrk   s    rI   r  HTTPServer.bind_addr  s    4 r'   c                 b    [        U[        5      (       a  US   S;   a  [        S5      eXl        g)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)rA  r   r4   r   )rA   rZ  s     rI   r  r!    s7     eU##aJ(> 6 
  r'   c                      U R                  5         g! [         a   nU R                  nU(       d  Xl        XeSnAf[         a   nU R                  nU(       d  X0l        X2eSnAff = f)z4Run the server forever, and stop it cleanly on exit.N)startrz  	interruptr{  )rA   kb_intr_excunderlying_interruptsys_exit_excs       rI   
safe_startHTTPServer.safe_start  sY    	9JJL  	8#'>> '!,7 	9#'>> '!-8		9s    
A%8A%A  A%c                 (   SU l         U R                  c  SU R                  -  U l        SU l        Sn[        R
                  " SS5      (       a:  [        R                  " S[        R                  [        R                  5      U l        O[        U R                  [        [        45      (       a   U R                  U R                  5        OvU R                  u  p4 [        R                  " UU[        R                   [        R                  S	[        R"                  5      nU H  nUu  ppn U R)                  XU5          O   U R                  (       d  [        R                  " U5      eU R                  R-                  S5        U R                  R/                  U R0                  5        [2        R4                  " U 5      U l        U R8                  R;                  5         SU l        [>        R>                  " 5       U l         g! [        R                   a4  nU< SU R                  < SU< S3n[        R                  " U5      UeSnAff = f! [        R$                   aQ    [        R                  nU R                  nS
U;   a  [        R&                  nUS-   nU[        R                  S	SU4/n GNf = f! [        R                   aL  nU< SU< SU< S3nU R                  (       a  U R                  R+                  5         SU l         SnAGM  SnAff = f)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_STREAMrA  r  r@  bytesbind_unix_socketr-  getaddrinfo	AF_UNSPEC
AI_PASSIVEgaierrorr   bindr   
settimeoutlistenrequest_queue_sizer   ConnectionManager_connectionsr  r$  r   r  r  )rA   r3  serrhostr   info	sock_typer  r}   afsocktyper^  
_canonnamesas                 rI   prepareHTTPServer.prepare  sW    == '$,,6DM *99\4(( --6>>6;M;MNDKe552%%dnn5 JDK))$$&&%%$ 693e'IIbE2	  {{,,s## 	q!4223 (99$? 	
99;i << 2*-t~~tDll3'T12" ?? K"NN	 NN	$; &I )F 2I"F$6$62yIJK || '.12t<C{{))+"&DKK	'sE   .G> AI	 *J1>I/II	A!J.-J.1LA LLc                    U R                   (       al  U R                  R                  5       nU[        L a  g[	        X5      n UR                  S5        SUl        UR!                  5         U R                   (       a  Mk  gg! [        [        R                  4 a     M  [         a<  nU R                  R                  [        U5      [        R                  SS9   SnANSnAff = f)z(Serve connections we can't handle a 503.Nz503 Service UnavailableTrq  )r   r  r?   _STOPPING_FOR_INTERRUPTr   r   OSErrorr   r|  r  r   rw  r   rx  r  r  r   )rA   r   requestr  s       rI   _serve_unservicableHTTPServer._serve_unservicableQ  s    jj++//1D..!$-G''(AB DKJJL+ jjj V112    %%H!--" & 	s   A? ?C!	C!%2CC!c                    [         R                  " U R                  S9R                  5         U R                  (       a[  U R
                  (       dJ   U R                  R                  U R                  5        U R                  (       a  U R
                  (       d  MJ  U R
                  (       aX  U R                  (       a)  [         R"                  " S5        U R                  (       a  M)  U R
                  (       a  U R
                  egg! [        [        4 a    e [         a"    U R                  S[        R                  SS9   Nf = f)z1Serve requests, after invoking :func:`prepare()`.targetzError in HTTPServer.serveTrq  g?N)	threadingThreadrO  r$  r   r%  r@  runexpiration_intervalrz  r{  r  rw  rx  r  _stopping_for_interruptr  sleeprk   s    rI   serveHTTPServer.servej  s    
 	 8 89??Ajj	!!%%d&>&>? jj >>..

3 ...~~nn$   &z2  /!--"  s   %D 9D?>D?c                 D    U R                  5         U R                  5         g)z]Run the server forever.

It is shortcut for invoking :func:`prepare()` then :func:`serve()`.
N)rI  rZ  rk   s    rI   r$  HTTPServer.start  s     	

r'   c              #      #    U R                  5         [        R                  " U R                  S9nSUl        UR                  5          Uv   U R                  5         g! U R                  5         f = f7f)z4Context manager for running this server in a thread.rR  TN)rI  rT  rU  rZ  daemonr$  stop)rA   threads     rI   _run_in_threadHTTPServer._run_in_thread  sP      	!!4	LIIKDIIKs   AA3	A A3A00A3c                 T    U R                   =(       a    U R                  R                  $ )z>Flag whether it is allowed to add a new keep-alive connection.)r   r@  rR  rk   s    rI   rR  'HTTPServer.can_add_keepalive_connection  s     zzLd//LLLr'   c                 ~    U R                   (       a  U R                  R                  U5        gUR                  5         g)z7Put an idle connection back into the ConnectionManager.N)r   r@  putr   rA   r   s     rI   put_connHTTPServer.put_conn  s(    ::!!$' JJLr'   c                 :   [         R                  R                  U< S35        [         R                  R                  5         U(       aS  [        R
                  " 5       n[         R                  R                  U5        [         R                  R                  5         gg)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)rA   r3  rr  rs  tbliness        rI   rw  HTTPServer.error_log  sd     	

C7"&

 ++-GJJW%JJ r'   c           	          U R                  U R                  UUUU R                  U R                  U R                  5      nU R                  X@R                  5      =o@l        U R                  U5      U l        U$ )z.Create (or recreate) the actual socket object.)prepare_socketr  nodelayr   r  bind_socketr,  resolve_real_bind_addr)rA   r  typer^  rl  s        rI   r;  HTTPServer.bind  sk    ""NNLLOO
 "--dNNCC{44T:r'   c           
         [         (       a   [        S5      eSn [        R                  " U R                  5        U R                  U[        R                  [        R                  SU R                  U R                  U R                  S	9n  [        R                  " UR!                  5       U5        S
n U R#                  Xa5      nU R)                  U5      n  U(       d   [        R*                  " X5        S
nU(       d  U R1                  S[2        R4                  S9  Xl        X`l	        U$ ! [
         a     N[         a  n[        U5      nSU;  a  e  SnAGNSnAf[         a)  n[        U5      nSU;  a  SU;  a  SU;  a  e  SnAGNNSnAff = f! [
         a    Sn Nf = f! [        R$                   a    UR'                  5         e f = f! [,         a    [        R.                  " XSS9   Nf = f! [
         a     GNf = f)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  r  ry  r^  rv  r   r  TF)follow_symlinksz(Failed to set socket fs mode permissions)rr  )r  r4   r0  unlinkr  rM  	TypeErrorr@  ru  r,  r  r4  rv  r   r  fchmodfilenorw  r-  r   rx  lchmodr  chmodrw  rx  ry  )rA   r  fs_permissionstyp_errerr_msgval_errrl  FS_PERMS_SETs           rI   r6  HTTPServer.bind_unix_socket  s   : B  	IIdnn%, "">>##LL(( # 
	!BIIdkkm^4L	##D4D
 //5			COIIi8  $ NN:oo  
 #E  	  	'lG9@GH H  	'lG9H(7F 	2  	! L	!
 || 	JJL	 & OHHYNO  		s}    D+ (F 4F# G1  G 6G1 +
F7	F EF%F		FF F #&G	G.+G1 -G..G1 1
G?>G?c                 P   US S u  p#US:H  nU R                   [        R                  [        R                  1;  a  [	        S5      eU(       a  [	        S5      e[        [        S5      (       a0  U R                  [        R                  [        R                  S5        g [        [        S5      (       a0  U R                  [        R                  [        R                  S5        g [        (       a0  U R                  [        R                  [        R                  S5        g [        S5      e)	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)r  r,  r3  r   r4   hasattr
setsockoptr  r  r  r  SO_REUSEADDRr  )socket_r  _hostr   IS_EPHEMERAL_PORTs        rI   _make_socket_reusable HTTPServer._make_socket_reusable!  s    m AI>>&..&//!BB;<<ABB 6,--v00&2H2H!LV^,,v00&2E2EqIZv00&2E2EqI%> r'   c                 V   [         R                   " X#U5      n[        R                  " U5        USS u  pU
S:H  nU(       a  U R                  XS9  [        (       d7  U(       d0   UR                  [         R                  [         R                  S5        U(       aJ  [        U[        [        45      (       d/  UR                  [         R                  [         R                  S5        Ub  UR                  U5      n[        [         S5      =(       a    U[         R                  :H  =(       a    U	S;   nU(       ac  [         R"                  " [$        [         R&                  5         UR                  [         R(                  [         R*                  S5        SSS5        U$ U$ ! , (       d  f       U$ = f)z%Create and prepare the socket object.Nr   r   r  r  r   r   >   ::::0	::0.0.0.0)r,  r   prevent_socket_inheritancer  r  r  r  r  rA  r@  r5  IPPROTO_TCPTCP_NODELAYr;  r  r   r   r   r  r-  r   r   )clsr  r  ry  r^  rv  r   r  rl  rB  r   r  listening_ipv6s                rI   ru  HTTPServer.prepare_socket;  sK    }}V51..t4r]
 AI%%d%H
/	 OOF--v/B/BAF:i#u>>OOF..0B0BAF"##D)D FJ' 3&//)322 	
 $$^V\\B ''&& C t CB s   0F
F(c                 (    U R                  U5        U $ )z#Bind the socket to given interface.)r;  r  s     rI   rw  HTTPServer.bind_socketv  s     	Yr'   c                     U R                  5       nU R                  [        R                  [        R                  1;   a   USS $ [        U[        5      (       a  [        U5      nU$ )z/Retrieve actual bind address from bound socket.Nr   )getsocknamer  r,  r3  r   rA  r5  r	   r  s     rI   rx  !HTTPServer.resolve_real_bind_addr|  s`    
 '')	>>NNOO
 

 Ra= i''YIr'   c                      U R                   R                  U5        g! [        R                   a    U R                  R                  U5         gf = f)z#Process an incoming HTTPConnection.N)r  rg  r  Fullr  rh  s     rI   process_connHTTPServer.process_conn  s@    	/MMd#zz 	/$$((.	/s    /AAc                     U R                   $ )zFlag interrupt of the server.)r.  rk   s    rI   r%  HTTPServer.interrupt  s     r'   c                 &    U R                   [        L $ )z8Return whether the server is responding to an interrupt.)r.  rL  rk   s    rI   rX  "HTTPServer._stopping_for_interrupt  s     "999r'   c                     [         U l        [        U[        5      (       a  U R	                  S5        [        U[
        5      (       a  U R	                  S5        U R                  5         Xl        g)zPerform 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)rL  r.  rA  rz  rw  r{  r`  )rA   r%  s     rI   r%  r    sN     2i!233NN>?i,,NN=>		#r'   c                    U R                   (       d  gSU l         U R                  R                  [        5        U R                  b5  U =R
                  [        R                  " 5       U R                  -
  -  sl        SU l        U R                  R                  5         [        U SS5      nU(       a  [        U R                  [        [        45      (       d   UR                  5       SS u  p#[        R                   " UU[        R"                  [        R$                  5       HV  nUu  pVpxn	Sn
 [        R                  " XVU5      n
U
R'                  S5        U
R)                  X#45        U
R+                  5         MX     [5        US5      (       a  UR+                  5         SU l        U R                  R+                  5         U R6                  R                  U R8                  5        g! [        R,                   a    U
(       a  U
R+                  5          M   M  f = f! [        R,                   a,  nUR.                  S   [0        R2                  ;  a  e  SnANSnAff = f)z5Gracefully shutdown a server that is serving forever.NFr,  r   g      ?r   r   )r   r  rg  rL  r  r  r  r@  r`  rT  rA  r  r@  r5  r  r,  r7  r8  r4  r<  connectr   r-  r  r   r.  r  r  shutdown_timeout)rA   rl  rB  r   r}   rE  rF  r^  rG  _sar  r  s               rI   r`  HTTPServer.stop  s   zz
 	  $$%<='NNdiikD,<,<<<N tXt,dnnsEl;;*!%!1!1!3BQ!7JD  &11((**	  @C<e 
* &bE BA LL-IItl3GGI & tW%%

DK!4001  &|| *  !	  !*7 || wwqz)G)GG 	 Hs+   H ,A
G""+HHI+"II)r   r@  r.  r  r  r  r  r6  r%  rh  ri  r   r  r  rX  r,  r/  ru  )r  ry   NFFF)r      Fr   )F)=rU   rV   rW   rX   rY   r   r.  r6  r  r  rX  r  r>  r  rS  rW  r   r  r/  r   r   r'  rv  r   ConnectionClassr   rh  ri  r  keep_alive_conn_limitrg   r  r  r  r  r  setterr)  rI  rO  rZ  r$  r   contextmanagerrb  rR  ri  rw  r;  r6  staticmethodr  classmethodru  rw  rx  r  r%  rX  r`  rZ   rM   r'   rI   r   r     sJ   JJGJFJ K?H&
 /  GG (G.H
 EMMLGN$O9K 
 !&
 J2A "'*1X5LnA
  6    (9I'V2%6
 	 	 M M(Rh  2  8 8t  
  */   : : $ $&:2r'   r   c                   $    \ rS rSrSrS rS rSrg)r   i  zDBase class to interface HTTPServer with other systems, such as WSGI.c                     Xl         g)z]Initialize Gateway instance with request.

Args:
    req (HTTPRequest): current HTTP request
Nr  )rA   r  s     rI   rg   Gateway.__init__  s	     r'   c                     [         e)z>Process the current request. Must be overridden in a subclass.)r  rk   s    rI   r7  Gateway.respond  s    !!r'   r  N)rU   rV   rW   rX   rY   rg   r7  rZ   rM   r'   rI   r   r     s    N"r'   r   z%cheroot.ssl.builtin.BuiltinSSLAdapterz&cheroot.ssl.pyopenssl.pyOpenSSLAdapter)builtin	pyopensslc                    [         U R                  5          n[        U[        5      (       aI  UR	                  S5      nXS-   S nUSU n [
        R                  U   nUc  [        e  [        XS5      nU$ U$ ! [         a"    [        U[        5       [        5       S/5      n N;f = f! [         a    [        SU< SU< S35      ef = f)z/Return an SSL adapter class for the given name.r  r   Nr   'z' object has no attribute ')ssl_adaptersr(  rA  r@  rfindrm  modulesKeyError
__import__globalslocalsrT  r  )nameadapterlast_dot	attr_namemod_pathmods         rI   r   r   	  s    4::<(G'3==%qLN+	9H%	B++h'C{ 	c-G N7N  	BXwy&(RDAC	B  	 7?K 	s   A8 )B' 8)B$#B$'C)r  )KrY   r   email.utilsrU  r  rx  r0  platformr  rer,  rm  rT  r  rs  rp  urllib.parser   	functoolsr   r   r   r   r   _compatr   r	   rm  r
   r   workersr   __all__systemr  r1  r   IS_GAEr  r  r  ImportErrorr  r  r   r   r   r{   r5   r8   r7   r;   r   r|   ASTERISKr   r  compiler@   r   r  rL  r>   r-   r   r   r   r   r   r   r   r   r   r  r   rM   r'   rI   <module>r     sE  AF   	  	   	  
      . . ! ,  __)+
 ? 
$b	)	4	45I	J '5v:  N 
 'Cf '&*--6>** 6=)) v}%%
  &2F 	ZZ'<)@ AB  $+  6 w%%GD( D(N, ,^ ^BW Wt~ ~BY	/ Y	/xC CL|2 |2~" "& 79aD  	
 !&Ss   9G' 'G98G9