
    GiHa                     |   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JrJrJ	r	J
r
JrJrJrJrJrJrJrJrJrJrJr  SSKJrJrJrJr  SSKJrJr  SrSrSr Sr!\RD                  " S	\RF                  " \!5      -  5      r$\RD                  " S
5      r%\RD                  " S5      r&\RD                  " S5      r'S r( " S S5      r)g)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                     SU;   a  g [         R                  " U 5      nU H
  nX4;   d  M
    g   g! [         a     gf = f)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        _/var/www/fortnox.synktek.com/backend/venv/lib/python3.13/site-packages/gunicorn/asgi/message.py_ip_in_allow_listr#   +   sQ     j!!&) =    s   0 
==c                       \ rS rSrSrSS jr\SS j5       rS rS r	SS jr
S rS	 rS
 rS rS 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S rS rSrg)AsyncRequest?   zwAsync HTTP request parser.

Parses HTTP/1.x requests using async I/O, reusing gunicorn's
parsing logic where possible.
c                    Xl         X l        X0l        X0l        X@l        S U l        S U l        S U l        S U l        S U l	        S U l
        / U l        / U l        UR                  (       a  SOSU l        SU l        SU l        S U l        UR$                  U l        U R$                  S:  d  U R$                  [&        :  a  [&        U l        UR(                  U l        U R(                  S::  d  U R(                  [*        :  a  [*        U l        UR,                  U l        U R,                  S:  a  [.        U l        U R,                  =(       d    [.        nU R(                  US-   -  S-   U l        S U l        SU l        S U l        SU l        g )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.   r0   max_header_field_sizes         r"   __init__AsyncRequest.__init__F   s_    "$$	
!$g&+##'  #&"8"8##a'**.>>&6D# %($<$<!%%*,,{:(3D%(+(D(D%((1,,HD) !% = = ]A]"&";";"Q&#(*+#, #      c                 T   #    U " XX45      nUR                  5       I Sh  vN   U$  N7f)ak  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.   r0   reqs         r"   parseAsyncRequest.parsev   s,     " #7jjl
 	s   (&(c                 6  #    [        5       nU R                  U5      I Sh  vN   U R                  R                  nUS:w  a)  U R                  S:X  a  U R                  X5      I Sh  vN nU R                  XR                  5      I Sh  vN u  p1U R                  U5        [        U5      n UR                  S5      nUSS S:H  nUS:  aP  U(       dI  U R                  U5      I Sh  vN   [        U5      n[        U5      U R                  :  a  [        S5      eOOMr  U(       a  U R                  R                  USS 5        O8U R!                  USU S	S
9U l        U R                  R                  XES-   S 5        U R%                  5         g GNm GN+ GN N7f)z$Parse the request from the unreader.Noff      

r*      
r   zmax buffer headersF)from_trailerr+   )	bytearray
_read_intor,   proxy_protocolr0   _handle_proxy_protocol
_read_liner>   _parse_request_linebytesfindlenrD   r   r-   unread_parse_headersr7   _set_body_reader)rI   bufmodelinedataidxdones          r"   rO   AsyncRequest._parse   sp    kooc""" xx&&5=T__133C>>C //#/F/FGG	  & Sz))K(C8w&DQwtooc***Szt9t666-.BCC 7   MM  ab*..tDSz.NDLMM  Agh0C 	#
 ? H +sH   FFAF&F'"F	F
AF'F(B'FFFFc                    #    U R                   R                  5       I Sh  vN nU(       d  [        [        U5      5      eUR	                  U5        g N17f)z7Read data from unreader and append to bytearray buffer.N)r-   readr   r`   extendrI   rf   ri   s      r"   r[   AsyncRequest._read_into   s=     ]]''))U3Z((

4 *s   AA2Ac                 b  #    [        U5      n UR                  S5      nUS:  a  XBs=:  a  S:  a  O  O[        XB5      eOW[        U5      S-
  Us=:  a  S:  a  O  O[        [        U5      U5      eU R	                  U5      I Sh  vN   [        U5      nM  USU [        X4S-   S 5      4$  N&7f)z<Read a line from buffer, returning (line, remaining_buffer).rX   r   r*   N)r`   ra   r
   rb   r[   rZ   )rI   rf   limitri   rj   s        r"   r^   AsyncRequest._read_line   s     Sz))G$Cax??*3664y1}u(q(&s4y%88//#&&&:D  Tc
Id78n566 's   BB/B-'B/c                 t  #    [        U5      S:  a*  U R                  U5      I Sh  vN   [        U5      S:  a  M*  US;   a6  USS [        :X  a)  U R                  5         U R	                  U5      I Sh  vN $ US;   a2  USS S:X  a)  U R                  5         U R                  U5      I Sh  vN $ U$  N N@ N
7f)zdHandle PROXY protocol detection and parsing.

Returns the buffer with proxy protocol data consumed.
   N)v2auto)v1rx      s   PROXY )rb   r[   r   _proxy_protocol_access_check_parse_proxy_protocol_v2_parse_proxy_protocol_v1)rI   rf   rg   s      r"   r]   #AsyncRequest._handle_proxy_protocol   s      #hm//#&&& #hm >!c#2h/&A--/66s;;; >!c"1g&:--/66s;;; 
 '
 <
 <s8   $B8B2B87B83B447B8+B6,B84B86B8c                 
   [        U R                  [        5      (       ad  [        U R                  S   U R                  R
                  U R                  R                  5       5      (       d  [        U R                  S   5      egg)z2Check if proxy protocol is allowed from this peer.r   N)
isinstancer.   tupler#   r,   proxy_allow_ipsproxy_allow_networksr   rI   s    r"   r{   )AsyncRequest._proxy_protocol_access_check   sh    t~~u--%dnnQ&79Q9Q&*hh&C&C&EG G'q(9::G .rM   c                   #    [        U5      nSU;  a,  U R                  U5      I Sh  vN   [        U5      nSU;  a  M,  UR                  S5      n[        USU 5      n[	        X#S-   S 5      nUR                  S5      n[        U5      S:w  a  [        U5      eUS   nUS   nUS   n	US;  a  [        S	U-  5      eUS
:X  aL   [        R                  " [        R                  U5        [        R                  " [        R                  U	5        OQUS:X  aK   [        R                  " [        R                  U5        [        R                  " [        R                  U	5         [        US   5      n
[        US   5      nSU
s=::  a  S::  a  O  OSUs=::  a  S::  d  O  [        SU-  5      eUUU
U	US.U l        U$  GN! [         a    [        U5      ef = f! [         a    [        U5      ef = f! [         a    [        SU-  5      ef = f7f)zPParse PROXY protocol v1 (text format).

Returns buffer with v1 header consumed.
rX   Nr*    rz   rV      )TCP4TCP6zprotocol '%s' not supportedr   r   r+      zinvalid port %sr   i  r\   client_addrclient_port
proxy_addr
proxy_port)r`   r[   ra   r   rZ   splitrb   r   socket	inet_ptonAF_INETOSErrorAF_INET6intr   r=   )rI   rf   ri   rj   rh   	remainingbitsprotos_addrd_addrs_portd_ports               r"   r}   %AsyncRequest._parse_proxy_protocol_v1   s     SzT!//#&&&:D T! ii D#J'd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#;<<	=sZ   &H
F9H
 BH
A
F< H
A
G !G. ==H
<GH
G++H
.HH
c                 T  #    [        U5      S:  a*  U R                  U5      I Sh  vN   [        U5      S:  a  M*  US   nUS   n[        R                  " S[	        USS 5      5      S   nUS-  S	-	  nUS
:w  a  [        SU-  5      eUS-  nU[        R                  [        R                  4;  a  [        SU-  5      eSU-   n[        U5      U:  a*  U R                  U5      I Sh  vN   [        U5      U:  a  M*  U[        R                  :X  a  SSSSSS.U l	        [        XS 5      $ US-  S	-	  nUS-  n	U	[        R                  :w  a  [        S5      e[	        USSU-    5      n
U[        R                  :X  a  US:  a  [        S5      e[        R                   " [        R"                  U
SS	 5      n[        R                   " [        R"                  U
S	S 5      n[        R                  " SU
SS 5      S   n[        R                  " SU
SS 5      S   nSnOU[        R$                  :X  a  US:  a  [        S5      e[        R                   " [        R&                  U
SS 5      n[        R                   " [        R&                  U
SS 5      n[        R                  " SU
SS 5      S   n[        R                  " SU
SS 5      S   nSnO<U[        R(                  :X  a  SSSSSS.U l	        [        XS 5      $ [        SU-  5      eUUUUUS.U l	        [        XS 5      $  GN GN>7f)zRParse PROXY protocol v2 (binary format).

Returns buffer with v2 header consumed.
   Nrv      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)rb   r[   structunpackr`   r   r   r   PROXYr=   rZ   r   STREAMr   INETr   	inet_ntopr   INET6r   r   )rI   rf   ver_cmd	fam_protolengthr1   commandtotal_header_sizefamilyprotocol	addr_datar   r   r   r   r   s                   r"   r|   %AsyncRequest._parse_proxy_protocol_v2!  s,     #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!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!3455 %%Dv%MNN $!!  $
  /011i '( 's.   $L(L"L(B+L('L%(L(=H&L(%L(c                 ~   UR                  SS5       Vs/ s H  n[        U5      PM     nn[        U5      S:w  a  [        [        U5      5      eUS   U l        U R
                  R                  (       di  [        R                  U R                  5      (       a  [        U R                  5      eS[        US   5      s=::  a  S::  d  O  [        U R                  5      e[        R                  U R                  5      (       d  [        U R                  5      eU R
                  R                  (       a  U R                  R                  5       U l        US   U l        [        U R                  5      S:X  a  [        [        U5      5      e [        U R                  5      nUR"                  =(       d    SU l        UR$                  =(       d    SU l        UR&                  =(       d    SU l        [(        R                  US   5      nUc  [+        US   5      e[-        UR/                  S5      5      [-        UR/                  S5      5      4U l        S	U R0                  s=::  a  S
:  d3  O  U R
                  R2                  (       d  [+        U R0                  5      eggs  snf ! [          a    [        [        U5      5      ef = f)zParse the HTTP request line.    r*   r   r      rV    NrV   r   )r*   r   )r   r   rb   r   r2   r,   !permit_unconventional_http_methodMETHOD_BADCHAR_REsearchr   TOKEN_RE	fullmatchcasefold_http_methodupperr3   r   r   r4   r5   r6   
VERSION_REr	   r   groupr1   "permit_unconventional_http_version)rI   
line_bytesbitr   partsmatchs         r"   r_    AsyncRequest._parse_request_line~  s   -7-=-=dA-FG-FcS!-FGt9>$\*%=>> 1gxx99 ''4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   JJ J<c                    U R                   n/ nUR                  S5       Vs/ s H  n[        U5      PM     nnSn0 n/ n	U(       a  On[        U R                  [
        5      (       a7  [        U R                  S   UR                  UR                  5       5      (       a  UR                  nUR                  n	U(       Ga  [        U5      U R                  :  a  [        S5      eUR                  S5      n
[        U
5      [        S5      -   nU
R                  S5      S::  a  [!        U
5      eU
R                  SS5      u  pU R                   R"                  (       a  UR%                  S5      n[&        R)                  U5      (       d  [+        U5      eUR-                  5       nUR/                  S5      /nU(       a  US   R1                  S	5      (       a  U R                   R2                  (       d  [5        U5      eUR                  S5      n
U[        U
5      [        S5      -   -  nXR6                  s=:  a  S:  a  O  O[        S
5      eUR9                  U
R/                  S5      5        U(       a  US   R1                  S	5      (       a  M  SR;                  U5      n[<        R?                  U5      (       a  [!        U5      eXR6                  s=:  a  S:  a  O  O[        S
5      eU(       d>  US:X  a8  URA                  5       S:X  a  U RB                  S:  a  OSU l"        O[G        U5      eX;   a;  XU   :H  nU(       a  SOSnU(       a  XRH                  :w  a
  [K        5       eOSnXl$        SU;   aO  X;   d  SU	;   a  OCU R                   RL                  S:X  a  O(U R                   RL                  S:X  a  GM  [+        U5      eUR9                  X45        U(       a  GM  U$ s  snf )z!Parse HTTP headers from raw data.rX   Fr   zlimit request headers fieldsz
:rV    	)r   	z!limit request headers fields sizez	 r   EXPECTz100-continuerV   rV   Tr(   r)   _r   	dangerousdrop)'r,   r   r   r   r.   r   r#   forwarded_allow_ipsforwarded_allow_networkssecure_scheme_headersforwarder_headersrb   r@   r   popra   r   strip_header_spacesrstripr   r   r   r   strip
startswithpermit_obsolete_foldingr   rB   appendjoin!RFC9110_5_5_INVALID_AND_DANGEROUSr   lowerr1   r<   r   r:   r   
header_map)rI   ri   rY   r,   r7   rh   linesscheme_headerr   r   currheader_lengthnamevaluesecurer:   s                   r"   rd   AsyncRequest._parse_headers  sA   hh04

70CD0Cd#0CD  "T^^U33"4>>!#4c6M6M#&#?#?#AC 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 #@#@D1D-.QRRTZZ./ E!H//<< HHUOE077>>#D))<<@q@)*MNNDH$4 ;;=N2||f, 6:3 ,E22,"==$* ,244 - %)M"(Kd{,7H0HXX((K7XX((F2+D11NND=)K eN k Es   Oc                    SnSnU R                    H  u  p4US:X  a  Ub
  [        SU S9eUnM  US:X  d  M$  UR                  S5       Vs/ s H  oUR                  5       PM     nnU H  nUR	                  5       S:X  a  U(       a
  [        SU S9eSnM,  UR	                  5       S	:X  a  U(       a
  [        SU S9eMS  UR	                  5       S
;   a#  U(       a
  [        SU S9eU R                  5         M  [        U5      e   M     U(       a=  U R                  S:  a
  [        SU S9eUb
  [        SU S9eSU l        SU l	        SU l
        gUbR   [        U5      R                  5       (       a  [        U5      nO
[        SU S9eUS:  a
  [        SU S9eX l	        X l
        gSU l	        SU l
        gs  snf ! [         a    [        SU S9ef = f)z'Determine how to read the request body.FNzCONTENT-LENGTH)rQ   zTRANSFER-ENCODING,rF   Tidentity)compressdeflategzipr   r   )r7   r   r   r   r   force_closer   r1   rF   rE   rH   str	isnumericr   r   )rI   rF   rE   r   r   vvalsvals           r"   re   AsyncRequest._set_body_reader  s   !\\MT''!-'(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2%(%8N'(8dCC !#$4$??"0#1  #$D#$D S =<  @#$4$??@s   F()F- 2
F- -Gc                     SU l         g)z/Mark connection for closing after this request.TN)r;   r   s    r"   r   AsyncRequest.force_close:  s	    rM   c                     U R                   (       a  gU R                   H<  u  pUS:X  d  M  UR                  5       R                  S5      nUS:X  a    gUS:X  a    g  O   U R                  S:*  $ )z8Check if connection should be closed after this request.T
CONNECTIONr   closez
keep-aliveFr   )r;   r7   r   r   r1   )rI   hr   s      r"   should_closeAsyncRequest.should_close>  sa    ??llFQL GGIOOE*<,&  # ||v%%rM   c                 `    UR                  5       nU R                   H  u  p#X!:X  d  M  Us  $    g)z.Get a header value by name (case-insensitive).N)r   r7   )rI   r   r  r   s       r"   
get_headerAsyncRequest.get_headerL  s,    zz|llFQy # rM   c                    #    U R                   S:X  a  gU R                  (       a  U R                  U5      I Sh  vN $ U R                  U5      I Sh  vN $  N N7f)zRead a chunk of the request body.

Args:
    size: Maximum bytes to read

Returns:
    bytes: Body data, empty bytes when body is exhausted
r   rM   N)rH   rF   _read_chunked_body_read_length_bodyrI   sizes     r"   	read_bodyAsyncRequest.read_bodyT  sO      1$<<00666//555 75s!   7AAAAAAc                    #    U R                   S::  a  g[        XR                   5      nU R                  R                  U5      I Sh  vN nU(       a  U =R                   [	        U5      -  sl         U$  N+7f)z"Read from a length-delimited body.r   rM   N)rH   minr-   rn   rb   )rI   r  to_readri   s       r"   r  AsyncRequest._read_length_bodye  s_     1$d001]]''00  CI-  1s   AA5A3,A5c                    #    U R                   c  U R                  5       U l          [        U R                   5      I Sh  vN $  N! [         a
    SU l         gf = f7f)zRead from a chunked body.Nr   rM   )rG   _chunked_body_readeranextStopAsyncIterationrH   r  s     r"   r  AsyncRequest._read_chunked_bodyp  sW     $ $ 9 9 ;D	t001111! 	#$D 	s8   #AA AA AA AAAAc                j  #     U R                  5       I Sh  vN nUR                  SS5      tp#U(       a  UR                  S5      n[        S U 5       5      (       a  [	        S5      e[        U5      S:X  a  [	        S5      e[        US5      nUS:X  a  U R                  5       I Sh  vN   gUnUS:  aY  U R                  R                  [        US	5      5      I Sh  vN nU(       d
  [        5       eU[        U5      -  nU7v   US:  a  MY  U R                  R                  S
5      I Sh  vN nUS:w  al  [        U5      S
:  aL  U R                  R                  S
[        U5      -
  5      I Sh  vN nU(       d  OXg-  n[        U5      S
:  a  ML  US:w  a  [	        S5      eGM   GN GN N N N?7f)z)Async generator for reading chunked body.N   ;rV   s    	c              3   *   #    U  H	  oS ;  v   M     g7f)s   0123456789abcdefABCDEFN ).0ns     r"   	<genexpr>4AsyncRequest._chunked_body_reader.<locals>.<genexpr>  s     Jz!55zs   zInvalid chunk sizer   r       r*   rX   zMissing chunk terminator)_read_chunk_size_liner   r   anyr   rb   r   _skip_trailersr-   rn   r  r   )rI   	size_line
chunk_sizer   r   ri   crlfmores           r"   r  !AsyncRequest._chunked_body_reader{  s    "88::I&__T15NJ'..v6
JzJ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LD	 $i!m
 7?'(BCCO : , F / Cse   F3F'BF3(F*)5F3F-.F3F3-F/.AF31F12F3F3*F3-F3/F31F3c                 6  #    [         R                  " 5       n U R                  R                  S5      I Sh  vN nU(       d
  [	        5       eUR                  U5        UR                  5       R                  S5      (       a  UR                  5       SS $ M~   N_7f)zRead a chunk size line.rV   NrX   )ioBytesIOr-   rn   r   writegetvalueendswithrp   s      r"   r#  "AsyncRequest._read_chunk_size_line  sr     jjl++A..D l"IIdO||~&&w//||~cr** .s   5BBA Bc                   #    [         R                  " 5       n U R                  R                  S5      I Sh  vN nU(       d  gUR	                  U5        UR                  5       nUR                  S5      (       a  gUS:X  a  gMl   NM7f)z(Skip trailer headers after chunked body.rV   NrW   rX   )r-  r.  r-   rn   r/  r0  r1  )rI   rf   ri   contents       r"   r%  AsyncRequest._skip_trailers  sm     jjl++A..DIIdOllnG,,'! .s   5BBABc                 V   #     U R                  S5      I Sh  vN nU(       d  gM#   N7f)zWDrain any unread body data.

Should be called before reusing connection for keepalive.
r"  N)r  )rI   ri   s     r"   
drain_bodyAsyncRequest.drain_body  s)     
 --D -s   )'))rG   rH   r<   r,   rF   rE   r6   r7   rB   r@   r>   rD   r2   r;   r4   r.   r=   r5   r/   r0   r:   r8   r-   r3   r1   N)rV   )r   )F)r"  )__name__
__module____qualname____firstlineno____doc__rK   classmethodrR   rO   r[   r^   r]   r{   r}   r|   r_   rd   re   r   r  r  r  r  r  r  r#  r%  r7  __static_attributes__r  rM   r"   r%   r%   ?   s    .!`  ($ L7",;9v[2z(7TZx4%l&6"		)DV	+rM   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?   rA   rC   RFC9110_5_6_2_TOKEN_SPECIALScompileescaper   r   r   r   r#   r%   r  rM   r"   <module>rG     s   
 
  	        : #   2 ::'2995Q+RSTJJx( ZZ*+
$&JJ{$; !(I
 I
rM   