
    AҐiHa                     |   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mZmZm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZ ddlmZmZ dZdZdZ dZ! ejD                  d	 ejF                  e!      z        Z$ ejD                  d
      Z% ejD                  d      Z& ejD                  d      Z'd Z( G d d      Z)y)z
Async version of gunicorn/http/message.py for ASGI workers.

Reuses the parsing logic from the sync version, adapted for async I/O.
    N)ExpectationFailedInvalidHeaderInvalidHeaderName
NoMoreDataInvalidRequestLineInvalidRequestMethodInvalidHTTPVersionLimitRequestLineLimitRequestHeadersUnsupportedTransferCodingObsoleteFoldingInvalidProxyLineInvalidProxyHeaderForbiddenProxyRequestInvalidSchemeHeaders)PP_V2_SIGNATURE	PPCommandPPFamily
PPProtocol)bytes_to_strsplit_request_urii  i   z!#$%&'*+-.^_`|~z[%s0-9a-zA-Z]+z[a-z#]zHTTP/(\d)\.(\d)z[\0\r\n]c                 r    d|v ry	 t        j                  |       }|D ]  }||v s y y# t        $ r Y yw xY w)zCheck if IP address is in the allow list.

    Args:
        ip_str: The IP address string to check
        allow_list: The original allow list (strings, may contain "*")
        networks: Pre-computed ipaddress.ip_network objects from config
    *TF)	ipaddress
ip_address
ValueError)ip_str
allow_listnetworksipnetworks        N/var/www/descvideos/venv/lib/python3.12/site-packages/gunicorn/asgi/message.py_ip_in_allow_listr#   +   sX     j!!&)  =   s   * 	66c                       e Zd ZdZddZedd       Zd Zd ZddZ	d Z
d Zd	 Zd
 Zd ZddZd Zd Zd Zd ZddZd Zd Zd Zd Zd Zd Zy)AsyncRequestzAsync HTTP request parser.

    Parses HTTP/1.x requests using async I/O, reusing gunicorn's
    parsing logic where possible.
    c                    || _         || _        || _        || _        || _        d | _        d | _        d | _        d | _        d | _	        d | _
        g | _        g | _        |j                  rdnd| _        d| _        d| _        d | _        |j$                  | _        | j$                  dk  s| j$                  t&        k\  rt&        | _        |j(                  | _        | j(                  dk  s| j(                  t*        kD  rt*        | _        |j,                  | _        | j,                  dk  rt.        | _        | j,                  xs t.        }| j(                  |dz   z  dz   | _        d | _        d| _        d | _        d| _        y )NhttpshttpFr         )cfgunreader	peer_addrremote_addr
req_numberversionmethoduripathqueryfragmentheaderstrailersis_sslscheme
must_close_expected_100_continueproxy_protocol_infolimit_request_lineMAX_REQUEST_LINElimit_request_fieldsMAX_HEADERSlimit_request_field_sizeDEFAULT_MAX_HEADERFIELD_SIZEmax_buffer_headerscontent_lengthchunked_body_reader_body_remaining)selfr+   r,   r-   r/   max_header_field_sizes         r"   __init__zAsyncRequest.__init__F   si    "$$	
!$g&+##'  #&"8"8##a'**.>>&6D# %($<$<!%%*,,{:(3D%(+(D(D%((1,,HD) !% = = ]A]"&";";"Q&#(*+#, #      c                 X   K    | ||||      }|j                          d{    |S 7 w)a  Parse an HTTP request from the stream.

        Args:
            cfg: gunicorn config object
            unreader: AsyncUnreader instance
            peer_addr: client address tuple
            req_number: request number on this connection (for keepalive)

        Returns:
            AsyncRequest: Parsed request object

        Raises:
            NoMoreData: If no data available
            Various parsing errors for malformed requests
        N)_parse)clsr+   r,   r-   r/   reqs         r"   parsezAsyncRequest.parsev   s1     " #xJ7jjl
 	s   *(*c                 $  K   t               }| j                  |       d{    | j                  j                  }|dk7  r)| j                  dk(  r| j                  ||       d{   }| j                  || j                         d{   \  }}| j                  |       t        |      }	 |j                  d      }|dd dk(  }|dk  rI|sG| j                  |       d{    t        |      }t        |      | j                  kD  rt        d      ni|r| j                  j                  |dd        n<| j!                  |d| d	
      | _        | j                  j                  ||dz   d        | j%                          y7 d7 #7 7 w)z$Parse the request from the unreader.Noff      

r)      
r   zmax buffer headersF)from_trailerr*   )	bytearray
_read_intor+   proxy_protocolr/   _handle_proxy_protocol
_read_liner=   _parse_request_linebytesfindlenrC   r   r,   unread_parse_headersr6   _set_body_reader)rH   bufmodelinedataidxdones          r"   rM   zAsyncRequest._parse   su    kooc""" xx&&5=T__133C>>C //#t/F/FGG	c  & Sz))K(C8w&DQwtooc***Szt9t666-.BCC  MM  ab*..tDSz.NDLMM  cAgh0C 	#
 ? H +sH   FFAF%F&#F	F
AF"F#B#FFFFc                    K   | j                   j                          d{   }|st        t        |            |j	                  |       y7 ,w)z7Read data from unreader and append to bytearray buffer.N)r,   readr   r]   extendrH   rc   rf   s      r"   rX   zAsyncRequest._read_into   s>     ]]''))U3Z((

4 *s   AA-Ac                 \  K   t        |      }	 |j                  d      }|dk\  r||cxkD  rdkD  rn nt        ||      nTt        |      dz
  |cxkD  rdkD  rn nt        t        |      |      | j	                  |       d{    t        |      }|d| t        ||dz   d       fS 7 &w)z<Read a line from buffer, returning (line, remaining_buffer).rU   r   r)   N)r]   r^   r
   r_   rX   rW   )rH   rc   limitrf   rg   s        r"   r[   zAsyncRequest._read_line   s     Sz))G$Cax??*3664y1}u(q(&s4y%88//#&&&:D  Tc
Id378n566 's   BB,B*'B,c                 b  K   t        |      dk  r(| j                  |       d{    t        |      dk  r(|dv r5|dd t        k(  r)| j                          | j	                  |       d{   S |dv r1|dd dk(  r)| j                          | j                  |       d{   S |S 7 7 =7 
w)ztHandle PROXY protocol detection and parsing.

        Returns the buffer with proxy protocol data consumed.
           N)v2auto)v1rr      s   PROXY )r_   rX   r   _proxy_protocol_access_check_parse_proxy_protocol_v2_parse_proxy_protocol_v1)rH   rc   rd   s      r"   rZ   z#AsyncRequest._handle_proxy_protocol   s      #hm//#&&& #hm >!c#2h/&A--/66s;;; >!c"1g&:--/66s;;; 
 '
 <
 <s8   #B/B)B/4B/-B+.4B/"B-#B/+B/-B/c                     t        | j                  t              r_t        | j                  d   | j                  j
                  | j                  j                               st        | j                  d         yy)z2Check if proxy protocol is allowed from this peer.r   N)
isinstancer-   tupler#   r+   proxy_allow_ipsproxy_allow_networksr   rH   s    r"   ru   z)AsyncRequest._proxy_protocol_access_check   s_    t~~u-%dnnQ&79Q9Q&*hh&C&C&EG'q(9::G .rK   c                   K   t        |      }d|vr)| j                  |       d{    t        |      }d|vr)|j                  d      }t        |d|       }t	        ||dz   d       }|j                  d      }t        |      dk7  rt        |      |d   }|d   }|d   }	|dvrt        d	|z        |d
k(  rJ	 t        j                  t        j                  |       t        j                  t        j                  |	       nN|dk(  rI	 t        j                  t        j                  |       t        j                  t        j                  |	       	 t        |d         }
t        |d         }d|
cxk  rdk  rn nd|cxk  rdk  sn t        d|z        |||
|	|d| _        |S 7 # t        $ r t        |      w xY w# t        $ r t        |      w xY w# t        $ r t        d|z        w xY ww)z`Parse PROXY protocol v1 (text format).

        Returns buffer with v1 header consumed.
        rU   Nr)    rt   rS      )TCP4TCP6zprotocol '%s' not supportedr   r   r*      zinvalid port %sr   i  rY   client_addrclient_port
proxy_addr
proxy_port)r]   rX   r^   r   rW   splitr_   r   socket	inet_ptonAF_INETOSErrorAF_INET6intr   r<   )rH   rc   rf   rg   re   	remainingbitsprotos_addrd_addrs_portd_ports               r"   rw   z%AsyncRequest._parse_proxy_protocol_v1   s     SzT!//#&&&:D T! ii D#J'd378n-	zz#t9>"4((Qaa(("#@5#HIIF?-  8  8 f_-  &9  &9	=a\Fa\F f%%A,@5,@"#4t#;<< $!!  $
  c '.  -&t,,-  -&t,,-  	="#4t#;<<	=sY   $G6F(G6B G6<AF+ G6AG G 09G6+G  G6GG6G33G6c                 (  K   t        |      dk  r(| j                  |       d{    t        |      dk  r(|d   }|d   }t        j                  dt	        |dd             d   }|dz  d	z	  }|d
k7  rt        d|z        |dz  }|t        j                  t        j                  fvrt        d|z        d|z   }t        |      |k  r(| j                  |       d{    t        |      |k  r(|t        j                  k(  rdddddd| _	        t        ||d       S |dz  d	z	  }|dz  }	|	t        j                  k7  rt        d      t	        |dd|z          }
|t        j                  k(  r|dk  rt        d      t        j                   t        j"                  |
dd	       }t        j                   t        j"                  |
d	d       }t        j                  d|
dd       d   }t        j                  d|
dd       d   }d}n|t        j$                  k(  r|dk  rt        d      t        j                   t        j&                  |
dd       }t        j                   t        j&                  |
dd       }t        j                  d|
dd       d   }t        j                  d|
dd       d   }d}n<|t        j(                  k(  rdddddd| _	        t        ||d       S t        d|z        |||||d| _	        t        ||d       S 7 7 0w)zbParse PROXY protocol v2 (binary format).

        Returns buffer with v2 header consumed.
           Nrp      z>H   r      r*   r)   zunsupported version %d   zunsupported command %dLOCALr   zonly TCP protocol is supportedz"insufficient address data for IPv4   
   r   $   z"insufficient address data for IPv6    "   r   UNSPECzunsupported address family %d)r_   rX   structunpackr]   r   r   r   PROXYr<   rW   r   STREAMr   INETr   	inet_ntopr   INET6r   r   )rH   rc   ver_cmd	fam_protolengthr0   commandtotal_header_sizefamilyprotocol	addr_datar   r   r   r   r   s                   r"   rv   z%AsyncRequest._parse_proxy_protocol_v2!  s7     #hm//#&&& #hm b'G	tU3r":%67: T>a'a<$%=%GHH D.9??IOO<<$%=%GHH K#h**//#&&& #h** ioo%")##""(D$ S!2!3455 d"q(t# z((($%EFF#bf-.	X]]"{()MNN%%fnni!nEF%%fnni!nEF]]41R9!<F]]42b)9:1=FEx~~%{()MNN%%fooy2GF%%fooyB7GHF]]42b)9:1=F]]42b)9:1=FEx& #+##""(D$ S!2!3455 %%Dv%MNN $!!  $
  ./011i '( 's.   #LLLB&LL L3HLLc                    |j                  dd      D cg c]  }t        |       }}t        |      dk7  rt        t        |            |d   | _        | j
                  j                  sbt        j                  | j                        rt        | j                        dt        |d         cxk  rdk  sn t        | j                        t        j                  | j                        st        | j                        | j
                  j                  r| j                  j                         | _        |d   | _        t        | j                        dk(  rt        t        |            	 t        | j                        }|j"                  xs d| _        |j$                  xs d| _        |j&                  xs d| _        t(        j                  |d         }|t+        |d         t-        |j/                  d            t-        |j/                  d            f| _        d	| j0                  cxk  rd
k  s.n | j
                  j2                  st+        | j0                        yyc c}w # t         $ r t        t        |            w xY w)zParse the HTTP request line.    r)   r   r      rS    NrS   r   )r)   r   )r   r   r_   r   r1   r+   !permit_unconventional_http_methodMETHOD_BADCHAR_REsearchr   TOKEN_RE	fullmatchcasefold_http_methodupperr2   r   r   r3   r4   r5   
VERSION_REr	   r   groupr0   "permit_unconventional_http_version)rH   
line_bytesbitr   partsmatchs         r"   r\   z AsyncRequest._parse_request_line~  s   -7-=-=dA-FGcS!GGt9>$\*%=>> 1gxx99 ''4*4;;77DG***4;;77!!$++.&t{{3388((++++-DK 7txx=A$\*%=>>	?%dhh/E JJ$"	[[&B
," $$T!W-=$T!W--EKKN+SQ-@A..88>>(66 ? /I H2  	?$\*%=>>	?s   I&-I+ +J	c                    | j                   }g }|j                  d      D cg c]  }t        |       }}d}i }g }	|rndt        | j                  t
              r2t        | j                  d   |j                  |j                               r|j                  }|j                  }	|rt        |      | j                  k\  rt        d      |j                  d      }
t        |
      t        d      z   }|
j                  d      dk  rt!        |
      |
j                  dd      \  }}| j                   j"                  r|j%                  d      }t&        j)                  |      st+        |      |j-                         }|j/                  d      g}|r|d   j1                  d	      r| j                   j2                  st5        |      |j                  d      }
|t        |
      t        d      z   z  }|| j6                  cxkD  rdkD  rt        d
       |j9                  |
j/                  d             |r|d   j1                  d	      rdj;                  |      }t<        j?                  |      rt!        |      || j6                  cxkD  rdkD  rt        d
       |s;|dk(  r6|jA                         dk(  r| jB                  dk  rnd| _"        ntG        |      ||v r2|||   k(  }|rdnd}|r|| jH                  k7  rtK               d}|| _$        d|v rI||	v sd|	v rn@| j                   jL                  dk(  rn&| j                   jL                  dk(  rt+        |      |j9                  ||f       |r|S c c}w )z!Parse HTTP headers from raw data.rU   Fr   zlimit request headers fieldsz
:rS    	)r   	z!limit request headers fields sizez	 r   EXPECTz100-continuerS   rS   Tr'   r(   _r   	dangerousdrop)'r+   r   r   ry   r-   rz   r#   forwarded_allow_ipsforwarded_allow_networkssecure_scheme_headersforwarder_headersr_   r?   r   popr^   r   strip_header_spacesrstripr   r   r   r   strip
startswithpermit_obsolete_foldingr   rA   appendjoin!RFC9110_5_5_INVALID_AND_DANGEROUSr   lowerr0   r;   r   r9   r   
header_map)rH   rf   rV   r+   r6   re   linesscheme_headerr   r   currheader_lengthnamevaluesecurer9   s                   r"   ra   zAsyncRequest._parse_headers  sC   hh04

70CDd#DD  "T^^U3"4>>!#4c6M6M#&#?#?#AC$'$=$=! # 5 57|t888)*HII99Q<DIF3Myy~"#D))**S!,KD%xx++{{5)%%d+'--::<D[['(E E!H//<xx77)$//yy|TS[!88 4#@#@D1D-.QRR ETZZ./ E!H//< HHUOE077>#D))t<<@q@)*MNN A  DH$4 ;;=N2||f, 6:3 ,E22,,"7"==$* ,244$(M"(DKd{,,7H0HXX((K7XX((F2+D11NND%=)K N k Es   M3c                 j   d}d}| j                   D ]  \  }}|dk(  r|t        d|       |}|dk(  s#|j                  d      D cg c]  }|j                          }}|D ]  }|j	                         dk(  r|rt        d|       d}(|j	                         d	k(  r|s>t        d|       |j	                         d
v r |rt        d|       | j                          }t        |        |rA| j                  dk  rt        d|       |t        d|       d| _        d| _	        d| _
        y|U	 t        |      j                         rt        |      }nt        d|       	 |dk  rt        d|       || _	        || _
        yd| _	        d| _
        yc c}w # t        $ r t        d|       w xY w)z'Determine how to read the request body.FNzCONTENT-LENGTH)rO   zTRANSFER-ENCODING,rE   Tidentity)compressdeflategzipr   r   )r6   r   r   r   r   force_closer   r0   rE   rD   rG   str	isnumericr   r   )rH   rE   rD   r   r   vvalsvals           r"   rb   zAsyncRequest._set_body_reader  s   !\\ 	?MT5''!-'(8dCC!&,,+0;;s+;<a	<< ?Cyy{i/""/0C"NN"&
2""/0C"NN(GG""/0C"NN((*7>>?	?, ||f$#$7TBB)#$4$??DL"&D#%D '@~&002%(%8N'(8dCC # !#$4$??"0D#1D  #$D#$D S =<  @#$4$??@s   F32F F2c                     d| _         y)z/Mark connection for closing after this request.TN)r:   r}   s    r"   r   zAsyncRequest.force_close:  s	    rK   c                     | j                   ry| j                  D ]9  \  }}|dk(  s|j                         j                  d      }|dk(  r y|dk(  r y n | j                  dk  S )z8Check if connection should be closed after this request.T
CONNECTIONr   closez
keep-aliveFr   )r:   r6   r   r   r0   )rH   hr   s      r"   should_closezAsyncRequest.should_close>  sh    ??ll 	FQL GGIOOE*<,& 	 ||v%%rK   c                 ^    |j                         }| j                  D ]  \  }}||k(  s|c S  y)z.Get a header value by name (case-insensitive).N)r   r6   )rH   r   r   r   s       r"   
get_headerzAsyncRequest.get_headerL  s5    zz|ll 	FQDy	 rK   c                    K   | j                   dk(  ry| j                  r| j                  |       d{   S | j                  |       d{   S 7 7 w)zRead a chunk of the request body.

        Args:
            size: Maximum bytes to read

        Returns:
            bytes: Body data, empty bytes when body is exhausted
        r   rK   N)rG   rE   _read_chunked_body_read_length_bodyrH   sizes     r"   	read_bodyzAsyncRequest.read_bodyT  sQ      1$<<00666//555 75s!   1AAAAAAc                    K   | j                   dk  ryt        || j                         }| j                  j                  |       d{   }|r| xj                   t	        |      z  c_         |S 7 &w)z"Read from a length-delimited body.r   rK   N)rG   minr,   rj   r_   )rH   r   to_readrf   s       r"   r   zAsyncRequest._read_length_bodye  sb     1$dD001]]''00  CI-  1s   AA0A.'A0c                    K   | j                   | j                         | _         	 t        | j                          d{   S 7 # t        $ r
 d| _        Y yw xY ww)zRead from a chunked body.Nr   rK   )rF   _chunked_body_readeranextStopAsyncIterationrG   r   s     r"   r   zAsyncRequest._read_chunked_bodyp  sX     $ $ 9 9 ;D	t001111! 	#$D 	s8   "AA AA AA AAAAc                .  K   	 | j                          d{   }|j                  dd      ^}}|r|j                  d      }t        d |D              rt	        d      t        |      dk(  rt	        d      t        |d      }|dk(  r| j                          d{    y|}|dkD  rR| j                  j                  t        |d	             d{   }|s
t               |t        |      z  }| |dkD  rR| j                  j                  d
       d{   }|dk7  rdt        |      d
k  rF| j                  j                  d
t        |      z
         d{   }|sn||z  }t        |      d
k  rF|dk7  rt	        d      7 s7 7 7 v7 6w)z)Async generator for reading chunked body.N   ;rS   s    	c              3   $   K   | ]  }|d v 
 yw)s   0123456789abcdefABCDEFN ).0ns     r"   	<genexpr>z4AsyncRequest._chunked_body_reader.<locals>.<genexpr>  s     J!155Js   zInvalid chunk sizer   r       r)   rU   zMissing chunk terminator)_read_chunk_size_liner   r   anyr   r_   r   _skip_trailersr,   rj   r  r   )rH   	size_line
chunk_sizer   r   rf   crlfmores           r"   r  z!AsyncRequest._chunked_body_reader{  s    "88::I&__T15NJ'..v6
JzJJ#$899:!##$899Z,JQ))+++ #Ia-!]]//It0DEE$,&SY&	
 a- ++A..Dw$i!m!%!3!3AD	M!BBDDLD	 $i!m
 7?'(BCCO : , F / Cse   FF
BFF4FF(F<FFAFFF8FFFFFc                   K   t        j                         }	 | j                  j                  d       d{   }|s
t	               |j                  |       |j                         j                  d      r|j                         dd S s7 Tw)zRead a chunk size line.rS   NrU   )ioBytesIOr,   rj   r   writegetvalueendswithrl   s      r"   r  z"AsyncRequest._read_chunk_size_line  sp     jjl++A..D l"IIdO||~&&w/||~cr** .s   4BBABc                    K   t        j                         }	 | j                  j                  d       d{   }|sy|j	                  |       |j                         }|j                  d      ry|dk(  ry`7 Aw)z(Skip trailer headers after chunked body.rS   NrT   rU   )r  r  r,   rj   r  r  r  )rH   rc   rf   contents       r"   r  zAsyncRequest._skip_trailers  sk     jjl++A..DIIdOllnG,'! .s   4A:A8AA:c                 J   K   	 | j                  d       d{   }|sy7 w)zgDrain any unread body data.

        Should be called before reusing connection for keepalive.
        r  N)r   )rH   rf   s     r"   
drain_bodyzAsyncRequest.drain_body  s*     
 --D -s   #!	#N)rS   )r   )F)r  )__name__
__module____qualname____doc__rJ   classmethodrP   rM   rX   r[   rZ   ru   rw   rv   r\   ra   rb   r   r   r   r   r   r   r  r  r  r   r
  rK   r"   r%   r%   ?   s    .!`  ($ L7",;9v[2z(7TZx4%l&6"		)DV	+rK   r%   )*r$  r  r   rer   r   gunicorn.http.errorsr   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   gunicorn.http.messager   r   r   r   gunicorn.utilr   r   r>   r@   rB   RFC9110_5_6_2_TOKEN_SPECIALScompileescaper   r   r   r   r#   r%   r
  rK   r"   <module>r-     s   
 
  	        : #   2 2::'92995Q+RSTBJJx( RZZ*+
$.BJJ{$; !(I
 I
rK   