
     iby                        S r SSKrSSKJr   " S S\5      r " S S\5      r " S S	\5      rS
r " S S\5      r	 " S S\5      r
 " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S \5      r " S! S"\5      r " S# S$\5      r " S% S&5      r " S' S(5      rg))z
HTTP parser for ASGI workers.

Provides callback-based parsing using either the fast C parser (gunicorn_h1c)
or the pure Python PythonProtocol fallback.
    N)IntEnumc                       \ rS rSrSrSrg)
ParseError   z&Base error raised during HTTP parsing. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       F/var/www/ias/venv/lib/python3.13/site-packages/gunicorn/asgi/parser.pyr   r          0r   r   c                       \ rS rSrSrSrg)InvalidProxyLine   zInvalid PROXY protocol v1 line.r   Nr   r   r   r   r   r      s    )r   r   c                       \ rS rSrSrSrg)InvalidProxyHeader   z!Invalid PROXY protocol v2 header.r   Nr   r   r   r   r   r      s    +r   r   s   

 
QUIT
c                        \ rS rSrSrSrSrSrg)	PPCommand    zPROXY protocol v2 commands.r      r   N)r	   r
   r   r   r   LOCALPROXYr   r   r   r   r   r       s    %EEr   r   c                   (    \ rS rSrSrSrSrSrSrSr	g)	PPFamily&   z#PROXY protocol v2 address families.r   r         r   N)
r	   r
   r   r   r   UNSPECINETINET6UNIXr   r   r   r   r   r   &   s    -FDEDr   r   c                   $    \ rS rSrSrSrSrSrSrg)
PPProtocol.   z&PROXY protocol v2 transport protocols.r   r   r!   r   N)	r	   r
   r   r   r   r#   STREAMDGRAMr   r   r   r   r(   r(   .   s    0FFEr   r(   c                       \ rS rSrSrSrg)LimitRequestLine5   z&Request line exceeds configured limit.r   Nr   r   r   r   r-   r-   5   r   r   r-   c                       \ rS rSrSrSrg)LimitRequestHeaders9   z+Too many headers or header field too large.r   Nr   r   r   r   r0   r0   9   s    5r   r0   c                       \ rS rSrSrSrg)InvalidRequestLine=   zInvalid request line.r   Nr   r   r   r   r3   r3   =       r   r3   c                       \ rS rSrSrSrg)InvalidRequestMethodA   zInvalid HTTP method.r   Nr   r   r   r   r7   r7   A       r   r7   c                       \ rS rSrSrSrg)InvalidHTTPVersionE   zInvalid HTTP version.r   Nr   r   r   r   r;   r;   E   r5   r   r;   c                       \ rS rSrSrSrg)InvalidHeaderNameI   zInvalid header name.r   Nr   r   r   r   r>   r>   I   r9   r   r>   c                       \ rS rSrSrSrg)InvalidHeaderM   zInvalid header value.r   Nr   r   r   r   rA   rA   M   r5   r   rA   c                       \ rS rSrSrSrg)UnsupportedTransferCodingQ   z$Unsupported Transfer-Encoding value.r   Nr   r   r   r   rD   rD   Q   s    .r   rD   c                       \ rS rSrSrSrg)InvalidChunkSizeU   z0Invalid chunk size in chunked transfer encoding.r   Nr   r   r   r   rG   rG   U   s    :r   rG   c                       \ rS rSrSrSrg)InvalidChunkExtensionY   z%Invalid chunk extension per RFC 9112.r   Nr   r   r   r   rJ   rJ   Y   s    /r   rJ   c                       \ rS rSrSrSr            SS jrS r\S 5       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g)PythonProtocol]   a_  Callback-based HTTP/1.1 parser (pure Python fallback).

Mirrors H1CProtocol interface for seamless switching between
the C extension and pure Python implementations.

Callbacks:
    on_message_begin: () -> None - Called when request starts
    on_url: (url: bytes) -> None - Called with request URL/path
    on_header: (name: bytes, value: bytes) -> None - Called for each header
    on_headers_complete: () -> bool - Called when headers done (return True to skip body)
    on_body: (chunk: bytes) -> None - Called with body data chunks
    on_message_complete: () -> None - Called when request is complete
)_on_message_begin_on_url
_on_header_on_headers_complete_on_body_on_message_complete_state_buffer_headers_listmethodpathhttp_versionheaderscontent_length
is_chunkedshould_keep_aliveis_complete_body_remaining
_skip_body_chunk_state_chunk_size_chunk_remaining_limit_request_line_limit_request_fields_limit_request_field_size"_permit_unconventional_http_method#_permit_unconventional_http_version_header_count_proxy_protocol_proxy_protocol_info_proxy_protocol_doneNc                    Xl         X l        X0l        X@l        XPl        X`l        Xpl        Xl        Xl        Xl	        Xl
        SU l        Xl        S U l        US:H  U l        US:w  a  SOSU l        [!        5       U l        / U l        S U l        S U l        S U l        / U l        S U l        SU l        SU l        SU l        SU l        SU l        SU l        SU l        SU l        g )Nr   offproxy_protocolrequest_lineFTsize) rO   rP   rQ   rR   rS   rT   re   rf   rg   rh   ri   rj   rk   rl   rm   rU   	bytearrayrV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   )selfon_message_beginon_url	on_headeron_headers_completeon_bodyon_message_completelimit_request_linelimit_request_fieldslimit_request_field_size!permit_unconventional_http_method"permit_unconventional_http_versionrp   s                r   __init__PythonProtocol.__init__z   s     "2#$7!$7! $6 %9")A&2S/3U0  .$(!$2e$;! +9E*A&~ { 	 "!%   ! # !r   c                    U R                   R                  U5        U R                   (       a  U R                  S:X  a  U R                  5       (       d  gOU R                  S:X  a  U R	                  5       (       d  gOvU R                  S:X  a  U R                  5       (       d  gOOU R                  S:X  a  U R                  5       (       d  gO(U R                  S:X  a  U R                  5       (       d  gOgU R                   (       a  M  gg)zProcess data, fire callbacks synchronously.

Args:
    data: bytes or bytearray of incoming data

Raises:
    ParseError: If the HTTP request is malformed
rp   rq   r[   bodychunkedN)rV   extendrU   _parse_proxy_protocol_parse_request_line_parse_headers_parse_body_parse_chunked_body)rt   datas     r   feedPythonProtocol.feed   s     	D!ll{{..1133 4.//11 2	)**,, -&'')) *	)//11 2 # lllr   c                     U R                   $ )z%Return proxy protocol info if parsed.)rl   rt   s    r   proxy_protocol_info"PythonProtocol.proxy_protocol_info   s     (((r   c                    SU l         U R                  R                  5         / U l        SU l        SU l        SU l        / U l        SU l        SU l	        SU l
        SU l        SU l        SU l        SU l        SU l        SU l        SU l        g)z#Reset for next request (keepalive).rq   NFTr   rr   )rU   rV   clearrW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   rj   r   s    r   resetPythonProtocol.reset   s    $	 "!%  " !r   c                     U R                   S:X  aB  U R                  S:X  a1  SU l         SU l        U R                  (       a  U R                  5         gggg)zMark parsing complete for EOF handling.

Call when no more data will be received. Handles edge cases like
chunked encoding without final trailer CRLF.
r   trailercompleteTN)rU   rb   r_   rT   r   s    r   finishPythonProtocol.finish   sO     ;;)#(9(9Y(F$DK#D(())+ )	 )G#r   c                    [        U R                  5      S:  a  gU R                  nUS;   a'  U R                  SS [        :X  a  U R	                  5       $ US;   a#  U R                  SS S:X  a  U R                  5       $ SU l        S	U l        g)
zParse PROXY protocol header if enabled.

Returns True if parsing is complete (or not applicable),
False if more data is needed.
   F)v2autoN)v1r      s   PROXY Trq   )lenrV   rk   PP_V2_SIGNATURE_parse_proxy_protocol_v2_parse_proxy_protocol_v1rm   rU   )rt   modes     r   r   $PythonProtocol._parse_proxy_protocol   s     t||r!## >!dll3B&7?&J0022 >!dll2A&6)&C0022 %)!$r   c                 "   U R                   R                  S5      nUS:X  a%  [        U R                   5      S:  a  [        S5      eg[	        U R                   SU 5      R                  S5      nU R                   SUS-   2	 UR                  S	5      n[        U5      S:  a  [        S
5      eUS   R                  5       nUS:X  a  SSSSSS.U l        OUS;   a|  [        U5      S:w  a  [        SU-  5      e US   nUS   n[        US   5      n[        US   5      nSUs=::  a  S::  a  O  OSUs=::  a  S::  d  O  [        S5      eUUUUUS.U l        O[        SU-  5      eSU l        SU l        g! [         a  n	[        SU	-  5      eSn	A	ff = f)zlParse PROXY protocol v1 (text format).

Format: PROXY <PROTO> <SRC_ADDR> <DST_ADDR> <SRC_PORT> <DST_PORT>

   
k   zPROXY v1 header too longFNlatin-1r!    zInvalid PROXY v1 liner   UNKNOWNrp   client_addrclient_port
proxy_addr
proxy_port)TCP4TCP6r   zInvalid PROXY v1 line for %sr"         zInvalid PROXY v1 port: %sr   i  zInvalid PROXY v1 port rangezUnknown PROXY v1 protocol: %sTrq   )rV   findr   r   bytesdecodesplitupperrl   int
ValueErrorrm   rU   )
rt   idxlinepartsprotos_addrd_addrs_portd_portes
             r   r   'PythonProtocol._parse_proxy_protocol_v1  s    ll("94<< 3&&'ABBT\\$3'(//	:LL#'" 

3u:>"#:;;a I #,##"")D% &&5zQ&'E'MNNHqqU1XU1X (5(Q&-AE-A&'DEE #(%%$$)D% ##BU#JKK$(!$%  H&'BQ'FGGHs   6&E1 1
F;F		Fc                 l   [        U R                  5      S:  a  gU R                  S   nU R                  S   n[        R                  " S[	        U R                  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 R                  5      U:  a  g[	        U R                  SU 5      nU R                  SU2	 U[        R                  :X  a  SSSSSS.U l	        SU l
        SU l        gUS-  S	-	  nUS-  n	U[        R                  :X  a  [        U5      S:  a  [        S5      eSR                  S USS	  5       5      n
SR                  S US	S  5       5      n[        R                  " SUSS 5      S   n[        R                  " SUSS 5      S   nU	[        R                   :X  a  SOSnGO#U[        R"                  :X  a  [        U5      S:  a  [        S5      e[        R                  " SUSS 5      n[        R                  " SUSS 5      nSR                  S  U 5       5      n
SR                  S! U 5       5      n[        R                  " SUSS" 5      S   n[        R                  " SUS"S 5      S   nU	[        R                   :X  a  S#OS$nO>U[        R$                  :X  a  S%SSSSS.U l	        SU l
        SU l        g[        S&U-  5      eUU
UUUS.U l	        SU l
        SU l        g)'z(Parse PROXY protocol v2 (binary format).r   Fr      z>H   r      r   r!   z Unsupported PROXY v2 version: %d   z Unsupported PROXY v2 command: %dNr   r   Trq   z"Invalid PROXY v2 IPv4 address data.c              3   8   #    U  H  n[        U5      v   M     g 7fNstr.0bs     r   	<genexpr>:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>  s     <mc!ffm   c              3   8   #    U  H  n[        U5      v   M     g 7fr   r   r   s     r   r   r     s     =nc!ffnr      
   r   UDP4$   z"Invalid PROXY v2 IPv6 address dataz>8Hr   :c              3   ,   #    U  H
  nS U-  v   M     g7fz%xNr   r   ws     r   r   r          81dQh   c              3   ,   #    U  H
  nS U-  v   M     g7fr   r   r   s     r   r   r     r   r   "   r   UDP6r#   z'Unsupported PROXY v2 address family: %d)r   rV   structunpackr   r   r   r   r   rl   rm   rU   r   r$   joinr(   r*   r%   r#   )rt   ver_cmdfam_protlengthversioncommand
total_size	addr_datafamilyprotocolr   r   r   r   r   s_wordsd_wordss                    r   r   'PythonProtocol._parse_proxy_protocol_v2O  s4    t||r! ,,r"<<#tU4<<2+>%?@C T>a'a<$%G'%QRR D.9??IOO<<$%G'%QRR &[
t||z) $,,r*56	LL*% ioo%")##"")D% )-D%(DK T/a'd?X]]"9~"()MNNXX<im<<FXX=i!n==F]]41R9!<F]]42b)9:1=F&**;*;;FEx~~%9~"()MNNmmE9Sb>:GmmE9R+;<GXX888FXX888F]]42b)9:1=F]]42b)9:1=F&**;*;;FEx& #+##"")D% )-D%(DK %%NQW%WXX $!!  %
! %)!$r   c                 <   U R                   R                  S5      nUS:X  a  gU R                  S:  a  XR                  :  a  [        S5      e[	        U R                   SU 5      nU R                   SUS-   2	 UR                  SS5      n[        U5      S	:w  a  [        S
5      eUS   U l        US   U l	        U R                  (       dD  U R                  U R                  5      (       d$  [        U R                  R                  S5      5      eUS   nUS:X  a  SU l        OUS:X  a  SU l        OtU R                  (       d  [!        UR                  S5      5      eUR#                  S5      (       a   [%        USS 5      nSU4U l        O[!        UR                  S5      5      eU R(                  (       a  U R)                  5         U R*                  (       a  U R+                  U R                  5        SU l        g! [&         a    [!        UR                  S5      5      ef = f)z,Parse request line, return True if complete.r   r   Fr   zRequest line is too largeNr!       r"   zInvalid request liner   r   s   HTTP/1.1r   r   s   HTTP/1.0r   r   s   HTTP/1.   r[   T)rV   r   re   r-   r   r   r   r3   rX   rY   rh   _is_valid_methodr7   r   rZ   ri   r;   
startswithr   r   rO   rP   rU   )rt   r   r   r   r   minors         r   r   "PythonProtocol._parse_request_line  s   ll("9 ##a'C2J2J,J"#>??T\\$3'(LL#'" 

4#u:?$%;<<Ah!H	 66((55*4;;+=+=i+HII (k! &D# &D;;(	)BCC!!*--H,E)*E
D% )	)BCC!!""$<<LL# " H,W^^I-FGGHs   /G6 6%Hc                     U R                   R                  S5      nUS:X  a  g[        U R                   SU 5      nU R                   SUS-   2	 U(       d  U R                  5         gU R                  S:  a'  [        U5      S-   U R                  :  a  [        S5      eU =R                  S	-  sl        U R                  S:  a%  U R                  U R                  :  a  [        S
5      eUR                  S5      nUS:X  a  [        S5      eUSU R                  5       nU R                  U5      (       d  [        UR                  S5      5      eX#S	-   S R                  5       nU R                  U5      (       a  [        S5      eUR                  5       nU R                   R#                  Xe45        U R$                  (       a  U R%                  Xe5        GM  )z3Parse headers, return True if headers are complete.Tr   r   FNr!   r   z!Request header field is too larger   zToo many headers   :zMissing colon in headerr   z"Invalid characters in header value)rV   r   r   _finalize_headersrg   r   r0   rj   rf   rA   strip_is_valid_tokenr>   r   _has_invalid_header_charslowerrW   appendrQ   )rt   r   r   colonnamevalue
name_lowers          r   r   PythonProtocol._parse_headers  s   ,,##G,Cbyds+,DXcAgX&&&( --1c$i!mdFdFd6d)*MNN !#))A-$2D2DtGaGa2a)*<== IIdOE{#$=>><%%'D''--'I(>??$**,E--e44#$HII J%%z&9:
2Q r   c                    U R                   U l        SnSnU R                   GH2  u  p4US:X  a/  Ub  [        S5      e [        U5      nUS:  a  [        S5      eUnM;  US:X  a  UR                  S	5       Vs/ s H  ofR                  5       PM     nnU H  nUR                  5       n	U	S
:X  a  U(       a  [        S5      eSnM/  U	S:X  a  U(       a  [        S5      eMI  U	S;   a  U(       a  [        S5      eSU l        Mj  [        UR                  S5      5      e   M  US:X  d  GM  UR                  5       nSU;   a
  SU l        GM"  SU;   d  GM+  SU l        GM5     U(       a?  U R                  S:  a  [        S5      eUb  [        S5      eSU l        SU l        SU l        OUb  Xl        Xl        OSU l        SU l        U R                  S:X  a;  U R                  (       a*  [        S U R                   5       5      n
U
(       d  SU l        U R                   (       a  U R!                  5       U l        U R"                  (       a1  SU l        SU l        U R(                  (       a  U R)                  5         ggU R                  (       a  SU l        SU l        gU R                  (       a  U R                  S:  a  SU l        gSU l        SU l        U R(                  (       a  U R)                  5         gg! [         a    [        S5      ef = fs  snf )aA  Called when all headers received.

Validates headers for request smuggling vulnerabilities:
- Rejects duplicate Content-Length headers
- Rejects requests with both Content-Length and Transfer-Encoding
- Rejects chunked Transfer-Encoding in HTTP/1.0
- Rejects stacked chunked encoding
- Validates Transfer-Encoding values
NFs   content-lengthzDuplicate Content-Length headerzInvalid Content-Length valuer   zNegative Content-Lengths   transfer-encoding   ,s   chunkedzStacked chunked encodingTs   identityz'Invalid Transfer-Encoding after chunked)s   compresss   deflates   gzipr   
   connections   close
   keep-aliver   z(Chunked encoding not allowed in HTTP/1.0z%Content-Length with Transfer-Encodingr   r   c              3   d   #    U  H&  u  pUS :H  =(       a    SUR                  5       ;   v   M(     g7f)r  r  N)r  )r   r  r	  s      r   r   3PythonProtocol._finalize_headers.<locals>.<genexpr>e  s1       #/KD %H-5;;=*HH#/s   .0r   r   rr   r   )rW   r[   rA   r   r   r   r  r  r^   rD   r   rZ   r]   r\   r`   anyrR   ra   rU   r_   rT   rb   )rt   r\   r   r  r	  cl_valuevvalsval	val_lowerhas_keepalives              r   r   PythonProtocol._finalize_headers  s    )) <<KD((!-'(IJJH"5zH a<'(ABB!)-- ,1;;t+<=+<a	+<=C #		I J.""/0J"KK"&"k1""/0Y"ZZ #"&HH""/0Y"ZZ16. 8

98MNN'  * &kkms?-2D*"c)-1D*W (\   6)#$NOO)#$KLL"DO"&D#%D '"0#1  #'D#$D  &4+A+A  #'<<  M !).&$$"779DO ??$DK#D(())+ )__#DK &D  T%8%81%< DK %DK#D(())+ )k " H'(FGGH >s   K*6L*L c                    U R                   (       a  U R                  S::  a  g[        [        U R                   5      U R                  5      n[	        U R                   SU 5      nU R                   SU2	 U =R                  U-  sl        U R
                  (       a  U R                  U5        U R                  S::  a/  SU l        SU l        U R                  (       a  U R                  5         g)z$Parse Content-Length delimited body.r   FNr   T)	rV   r`   minr   r   rS   rU   r_   rT   )rt   
chunk_sizechunks      r   r   PythonProtocol._parse_body  s    ||t33q8T\\*D,@,@A
dll;J/0LL*%
*==MM% 1$$DK#D(())+r   c                    U R                   (       Ga  U R                  S:X  Ga  U R                   R                  S5      nUS:X  a  g[        U R                   SU 5      nU R                   SUS-   2	 UR                  S5      nUS:w  a  X#S-   S nS	U;   a  [	        S
5      eUSU nX"R                  5       :w  a  [        S5      eU(       d  [        S5      eU H  nUS;  d  M  [        S5      e    [        US5      U l        U R                  S:X  a	  SU l        GOU R                  U l
        SU l        GOU R                  S:X  a  U R                   (       d  g[        [        U R                   5      U R                  5      n[        U R                   SU 5      nU R                   SU2	 U =R                  U-  sl
        U R                  (       a  U R                  U5        U R                  S:X  a  SU l        OU R                  S:X  a1  [        U R                   5      S:  a  gU R                   SS2	 SU l        OU R                  S:X  a  U R                   R                  S5      nUS:X  a  g[        U R                   SU 5      nU R                   SUS-   2	 U(       d0  SU l        SU l        U R                   (       a  U R!                  5         gU R                   (       a  GM  g! [         a    [        S5      ef = f)z Parse chunked transfer encoding.rr   r   r   FNr!      ;r      zbare CR not allowedzWhitespace in chunk sizezEmpty chunk sizes   0123456789abcdefABCDEFzInvalid character in chunk sizer   zInvalid chunk sizer   r   r   crlfr   T)rV   rb   r   r   rJ   r  rG   r   rc   r   rd   r  r   rS   rU   r_   rT   )	rt   r   	size_line	semicolon	chunk_extcto_readr  r   s	            r   r   "PythonProtocol._parse_chunked_body  s   lll  F*ll''0"9 !$,,t"45	LL#'* &NN40	? )a-. 9I	)34IJJ )*9 5I  11*+EFF *+=>> #A 99./PQQ #A'*9b'9D$ ##q((1D%,0,<,<D)(.D%""f,|| c$,,/1F1FGdll8G45LL'*%%0%==MM%(((A-(.D%""f,t||$q( LL!$$*!""i/ll''0"9 T\\$3/0LL#'*",DK'+D$00113e lllh g " A*+?@@As   /K K3c                     U(       d  gS[        U5      s=::  a  S::  d   g  gU H  nUS;   d  M    g   U R                  U5      $ )z>Check if method is valid token with conventional restrictions.Fr"   r   s   abcdefghijklmnopqrstuvwxyz#)r   r  )rt   rX   r&  s      r   r   PythonProtocol._is_valid_method  sM    CK%2% &A22  ##F++r   c                 R    U(       d  gU H  nUS:  d  US:  a    gUS;   d  M    g   g)z6Check if data contains only RFC 9110 token characters.F!   ~   s   "(),/:;<=>?@[\]{}"Tr   )rt   r   r&  s      r   r  PythonProtocol._is_valid_token  s3    A4x1t8**  r   c                 <    SU;   =(       d    SU;   =(       d    SU;   $ )z&Check for NUL, CR, LF in header value.    r!     
r   )rt   r	  s     r   r  (PythonProtocol._has_invalid_header_chars  s    %C5E>CUe^Cr   )r`   rV   rd   rc   rb   rj   rW   rg   rf   re   rS   rQ   rR   rO   rT   rP   rh   ri   rk   rm   rl   ra   rU   r\   r[   rZ   r]   r_   rX   rY   r^   )NNNNNN  d   r3  FFro   )r	   r
   r   r   r   	__slots__r   r   propertyr   r   r   r   r   r   r   r   r  r   r   r   r  r  r   r   r   r   rM   rM   ]   s    I     !%*/+09"v< ) )(,2;z`D3j*3Xm,^*Vp,
Dr   rM   c                   B    \ rS rSrSrSrS r\S
S j5       rS r	S r
Srg	)CallbackRequesti  zpRequest object built from callback parser state.

Works with both H1CProtocol (C extension) and PythonProtocol.
rX   urirY   queryfragmentr   r[   headers_bytesschemeraw_pathr\   r   
must_closer   _expect_100_continuec                     S U l         S U l        S U l        S U l        S U l        S U l        / U l        / U l        SU l        SU l	        SU l
        SU l        SU l        S U l        SU l        g )Nhttpr   r   Fr9  r   s    r   r   CallbackRequest.__init__  so    	
#' $)!r   c                    SSK Jn  U " 5       nUR                  R                  S5      Ul        UR                  nSU;   aL  UR                  SS5      u  pgXdl        U" U5      R                  SSS9Ul        UR                  S	5      Ul        O(XTl        U" U5      R                  SSS9Ul        S
Ul        UR                  S	5      Ul        S
Ul	        UR                  Ul        [        [        USS5      =(       d    UR                  5      Ul        UR                   VV	s/ s H5  u  pUR                  S	5      R!                  5       U	R                  S	5      4PM7     sn	nUl        U(       a  SOSUl        UR$                  =(       d    SUl        UR&                  Ul        UR*                  (       + Ul        UR                   H+  u  pU
S:X  d  M  UR/                  5       S:X  d  M#  SUl          U$    U$ s  sn	nf )zBuild request from callback parser state.

Args:
    parser: H1CProtocol or PythonProtocol instance
    is_ssl: Whether connection is SSL/TLS

Returns:
    CallbackRequest instance
r   )unquote_to_bytesascii   ?r   zutf-8replace)errorsr    asgi_headersNhttpsrC  s   expects   100-continueT)urllib.parserF  rX   r   rY   r   r?  r;  r:  r<  rZ   r   listgetattrr[   r=  r   r>  r\   r]   r   r^   r@  r  rA  )clsparseris_sslrF  reqraw_url	path_part
query_partnr  r  r	  s               r   from_parserCallbackRequest.from_parser*  s    	2e]]))'2
 ++7?$+MM$$:!I$L'	299')9TCH")))4CI"L'077	7RCHCI..+))
 !!F!X&..Y 
& XXi &&(!((9*=>&

 !'WF
#227a''#555 ">>KDy U[[]o%E+/(
 *
 
!
s   <G2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
CONNECTIONz 	closez
keep-aliveFr   )r@  r[   r  r  r   )rt   r  r	  r  s       r   should_closeCallbackRequest.should_closec  sc    ??<<KD|#KKM''.<,&  ( ||v%%r   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   r[   )rt   r  hr  s       r   
get_headerCallbackRequest.get_headerq  s,    zz|LLDAy ! r   )rA  r   r\   r<  r[   r=  rX   r@  rY   r   r;  r?  r>  r:  r   N)F)r	   r
   r   r   r   r5  r   classmethodrY  r^  rb  r   r   r   r   r8  r8    s2    
I*" 6 6p&r   r8  )r   r   enumr   	Exceptionr   r   r   r   r   r   r(   r-   r0   r3   r7   r;   r>   rA   rD   rG   rJ   rM   r8  r   r   r   <module>rg     s   
  1 1*z *, ,
 F w  1z 16* 6   :    
  J  /
 /;z ;0J 0l
D l
D^k kr   