
    [iby                        d Z ddlZddlmZ  G d de      Z G d de      Z G d d	e      Zd
Z G d de      Z	 G d de      Z
 G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d d e      Z G d! d"e      Z G d# d$e      Z G d% d&      Z G d' d(      Zy))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                       e Zd ZdZy)
ParseErrorz&Base error raised during HTTP parsing.N__name__
__module____qualname____doc__     e/var/www/html/userprofiledev.eatanceapp.com/venv/lib/python3.12/site-packages/gunicorn/asgi/parser.pyr   r          0r   r   c                       e Zd ZdZy)InvalidProxyLinezInvalid PROXY protocol v1 line.Nr   r   r   r   r   r      s    )r   r   c                       e Zd ZdZy)InvalidProxyHeaderz!Invalid PROXY protocol v2 header.Nr   r   r   r   r   r      s    +r   r   s   

 
QUIT
c                       e Zd ZdZdZdZy)	PPCommandzPROXY protocol v2 commands.r      N)r   r   r	   r
   LOCALPROXYr   r   r   r   r       s    %EEr   r   c                        e Zd ZdZdZdZdZdZy)PPFamilyz#PROXY protocol v2 address families.r   r         N)r   r   r	   r
   UNSPECINETINET6UNIXr   r   r   r   r   &   s    -FDEDr   r   c                       e Zd ZdZdZdZdZy)
PPProtocolz&PROXY protocol v2 transport protocols.r   r   r   N)r   r   r	   r
   r   STREAMDGRAMr   r   r   r!   r!   .   s    0FFEr   r!   c                       e Zd ZdZy)LimitRequestLinez&Request line exceeds configured limit.Nr   r   r   r   r%   r%   5   r   r   r%   c                       e Zd ZdZy)LimitRequestHeadersz+Too many headers or header field too large.Nr   r   r   r   r'   r'   9   s    5r   r'   c                       e Zd ZdZy)InvalidRequestLinezInvalid request line.Nr   r   r   r   r)   r)   =       r   r)   c                       e Zd ZdZy)InvalidRequestMethodzInvalid HTTP method.Nr   r   r   r   r,   r,   A       r   r,   c                       e Zd ZdZy)InvalidHTTPVersionzInvalid HTTP version.Nr   r   r   r   r/   r/   E   r*   r   r/   c                       e Zd ZdZy)InvalidHeaderNamezInvalid header name.Nr   r   r   r   r1   r1   I   r-   r   r1   c                       e Zd ZdZy)InvalidHeaderzInvalid header value.Nr   r   r   r   r3   r3   M   r*   r   r3   c                       e Zd ZdZy)UnsupportedTransferCodingz$Unsupported Transfer-Encoding value.Nr   r   r   r   r5   r5   Q   s    .r   r5   c                       e Zd ZdZy)InvalidChunkSizez0Invalid chunk size in chunked transfer encoding.Nr   r   r   r   r7   r7   U   s    :r   r7   c                       e Zd ZdZy)InvalidChunkExtensionz%Invalid chunk extension per RFC 9112.Nr   r   r   r   r9   r9   Y   s    /r   r9   c                       e Zd ZdZdZ	 	 	 	 	 	 	 	 	 	 	 	 ddZd Zed        Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)PythonProtocola  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                    || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        d| _        || _        d | _        |dk(  | _        |dk7  rdnd| _        t!               | _        g | _        d | _        d | _        d | _        g | _        d | _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        y )Nr   offproxy_protocolrequest_lineFTsize) r<   r=   r>   r?   r@   rA   rR   rS   rT   rU   rV   rW   rX   rY   rZ   rB   	bytearrayrC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   )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_versionr]   s                r   __init__zPythonProtocol.__init__z   s    "2#$7!$7! $6 %9")A&2S/3U0  .$(!$2e$;! +9E*A&~ { 	 "!%   ! # !r   c                    | j                   j                  |       | j                   r| j                  dk(  r| j                         sy| j                  dk(  r| j	                         sby| j                  dk(  r| j                         sBy| j                  dk(  r| j                         s"y| j                  dk(  r| j                         syy| j                   ryy)zProcess data, fire callbacks synchronously.

        Args:
            data: bytes or bytearray of incoming data

        Raises:
            ParseError: If the HTTP request is malformed
        r]   r^   rH   bodychunkedN)rC   extendrB   _parse_proxy_protocol_parse_request_line_parse_headers_parse_body_parse_chunked_body)ra   datas     r   feedzPythonProtocol.feed   s     	D!ll{{..113.//1	)**,&'')	)//1# llr   c                     | j                   S )z%Return proxy protocol info if parsed.)rY   ra   s    r   proxy_protocol_infoz"PythonProtocol.proxy_protocol_info   s     (((r   c                    d| _         | j                  j                          g | _        d| _        d| _        d| _        g | _        d| _        d| _	        d| _
        d| _        d| _        d| _        d| _        d| _        d| _        d| _        y)z#Reset for next request (keepalive).r^   NFTr   r_   )rB   rC   clearrD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rW   rz   s    r   resetzPythonProtocol.reset   s    $	 "!%  " !r   c                     | j                   dk(  r<| j                  dk(  r,d| _         d| _        | j                  r| j                          yyyy)zMark parsing complete for EOF handling.

        Call when no more data will be received. Handles edge cases like
        chunked encoding without final trailer CRLF.
        rp   trailercompleteTN)rB   rO   rL   rA   rz   s    r   finishzPythonProtocol.finish   sO     ;;)#(9(9Y(F$DK#D(())+ )	 )G#r   c                 
   t        | j                        dk  ry| j                  }|dv r&| j                  dd t        k(  r| j	                         S |dv r"| j                  dd dk(  r| j                         S d| _        d	| _        y)
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 Tr^   )lenrC   rX   PP_V2_SIGNATURE_parse_proxy_protocol_v2_parse_proxy_protocol_v1rZ   rB   )ra   modes     r   rr   z$PythonProtocol._parse_proxy_protocol   s     t||r!## >!dll3B&7?&J0022 >!dll2A&6)&C0022 %)!$r   c                 2   | j                   j                  d      }|dk(  r$t        | j                         dkD  rt        d      yt	        | j                   d|       j                  d      }| j                   d|dz   = |j                  d	      }t        |      dk  rt        d
      |d   j                         }|dk(  rdddddd| _        n|dv rt        |      dk7  rt        d|z        	 |d   }|d   }t        |d         }t        |d         }d|cxk  rdk  r$n t        d      d|cxk  rdk  st        d       t        d      |||||d| _        nt        d|z        d| _        d| _        y# t        $ r}	t        d|	z        d}	~	ww xY w)z|Parse 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r]   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: %sTr^   )rC   findr   r   bytesdecodesplitupperrY   int
ValueErrorrZ   rB   )
ra   idxlinepartsprotos_addrd_addrs_portd_portes
             r   r   z'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(&'DEE ./&-AE-A&'DEE .B&'DEE #(%%$$)D% ##BU#JKK$(!$%  H&'BQ'FGGHs   /&E: :	FFFc                 D   t        | j                        dk  ry| j                  d   }| j                  d   }t        j                  dt	        | j                  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        | j                        |k  ryt	        | j                  d|       }| j                  d|= |t        j                  k(  rdddddd| _	        d| _
        d| _        y|dz  d	z	  }|dz  }	|t        j                  k(  rt        |      dk  rt        d      dj                  d |dd	 D              }
dj                  d |d	d D              }t        j                  d|dd       d   }t        j                  d|dd       d   }|	t        j                   k(  rdnd}n|t        j"                  k(  rt        |      dk  rt        d      t        j                  d|dd       }t        j                  d|dd       }dj                  d  |D              }
dj                  d! |D              }t        j                  d|dd"       d   }t        j                  d|d"d       d   }|	t        j                   k(  rd#nd$}n=|t        j$                  k(  rd%ddddd| _	        d| _
        d| _        yt        d&|z        ||
|||d| _	        d| _
        d| _        y)'z(Parse PROXY protocol v2 (binary format).   Fr      z>H   r      r   r   z Unsupported PROXY v2 version: %d   z Unsupported PROXY v2 command: %dNr   r   Tr^   z"Invalid PROXY v2 IPv4 address data.c              3   2   K   | ]  }t        |        y wNstr.0bs     r   	<genexpr>z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>  s     <mc!fm   c              3   2   K   | ]  }t        |        y wr   r   r   s     r   r   z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>  s     =nc!fnr      
   r   UDP4$   z"Invalid PROXY v2 IPv6 address dataz>8H    :c              3   &   K   | ]	  }d |z    ywz%xNr   r   ws     r   r   z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>       81dQh   c              3   &   K   | ]	  }d |z    ywr   r   r   s     r   r   z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>  r   r   "   r   UDP6r   z'Unsupported PROXY v2 address family: %d)r   rC   structunpackr   r   r   r   r   rY   rZ   rB   r   r   joinr!   r"   r   r   )ra   ver_cmdfam_protlengthversioncommand
total_size	addr_datafamilyprotocolr   r   r   r   r   s_wordsd_wordss                    r   r   z'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                    | j                   j                  d      }|dk(  ry| j                  dkD  r|| j                  kD  rt        d      t	        | j                   d|       }| j                   d|dz   = |j                  dd      }t        |      d	k7  rt        d
      |d   | _        |d   | _	        | j                  s?| j                  | j                        s$t        | j                  j                  d            |d   }|dk(  rd| _        nw|dk(  rd| _        nj| j                  st!        |j                  d            |j#                  d      r	 t%        |dd       }d|f| _        nt!        |j                  d            | j(                  r| j)                          | j*                  r| j+                  | j                         d| _        y# t&        $ r t!        |j                  d            w xY w)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.   rH   T)rC   r   rR   r%   r   r   r   r)   rE   rF   rU   _is_valid_methodr,   r   rG   rV   r/   
startswithr   r   r<   r=   rB   )ra   r   r   r   r   minors         r   rs   z"PythonProtocol._parse_request_line  s   ll("9 ##a'C$2J2J,J"#>??T\\$3'(LL#'" 

4#u:?$%;<<Ah!H	 66((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   G $G7c                 v   	 | j                   j                  d      }|dk(  ryt        | j                   d|       }| j                   d|dz   = |s| j                          y| j                  dkD  r&t        |      dz   | j                  kD  rt        d      | xj                  d	z  c_        | j                  dkD  r$| j                  | j                  kD  rt        d
      |j                  d      }|dk(  rt        d      |d| j                         }| j                  |      st        |j                  d            ||d	z   d j                         }| j                  |      rt        d      |j                         }| j                   j#                  ||f       | j$                  r| j%                  ||       )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)rC   r   r   _finalize_headersrT   r   r'   rW   rS   r3   strip_is_valid_tokenr1   r   _has_invalid_header_charslowerrD   appendr>   )ra   r   r   colonnamevalue
name_lowers          r   rt   zPythonProtocol._parse_headers  s   ,,##G,Cbyds+,DXcAgX&&&( --1c$i!mdFdFd6d)*MNN !#))A-$2D2DtGaGa2a)*<== IIdOE{#$=>><%%'D''-'I(>??$**,E--e4#$HII J%%z5&9:
E2Q r   c                 Z   | j                   | _        d}d}| j                  D ]	  \  }}|dk(  r,|t        d      	 t        |      }|dk  rt        d      |}8|dk(  r|j                  d	      D cg c]  }|j                          }}|D ]l  }|j                         }	|	d
k(  r|rt        d      d}(|	dk(  r|s0t        d      |	dv r|rt        d      d| _        Tt        |j                  d             |dk(  s|j                         }d|v rd| _        d|v sd| _         |r=| j                  dk  rt        d      |t        d      d| _        d| _        d| _        n||| _        || _        nd| _        d| _        | j                  dk(  r1| j                  r%t        d | j                  D              }
|
sd| _        | j                   r| j!                         | _        | j"                  r,d| _        d| _        | j(                  r| j)                          yy| j                  rd| _        d| _        y| j                  r| j                  dkD  rd| _        yd| _        d| _        | j(                  r| j)                          yy# t        $ r t        d      w xY wc c}w )ay  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   T   K   | ]   \  }}|d k(  xr d|j                         v  " yw)r   r   N)r   )r   r   r   s      r   r   z3PythonProtocol._finalize_headers.<locals>.<genexpr>e  s4       #/KD% %H-5;;=*HH#/s   &(r   rp   r_   ro   )rD   rH   r3   r   r   r   r   r   rK   r5   r   rG   rJ   rI   rM   anyr?   rN   rB   rL   rA   rO   )ra   rI   rp   r   r   cl_valuevvalsval	val_lowerhas_keepalives              r   r   z 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 '"0D#1D  #'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   J2J(J%c                    | j                   r| j                  dk  ryt        t        | j                         | j                        }t	        | j                   d|       }| j                   d|= | xj                  |z  c_        | j
                  r| j                  |       | j                  dk  r*d| _        d| _        | j                  r| j                          y)z$Parse Content-Length delimited body.r   FNr   T)	rC   rM   minr   r   r@   rB   rL   rA   )ra   
chunk_sizechunks      r   ru   zPythonProtocol._parse_body  s    ||t33q8T\\*D,@,@A
dll;J/0LL*%
*==MM% 1$$DK#D(())+r   c                    | j                   r| j                  dk(  r| j                   j                  d      }|dk(  ryt        | j                   d|       }| j                   d|dz   = |j                  d      }|dk7  r||dz   d }d	|v rt	        d
      |d| }||j                         k7  rt        d      |st        d      |D ]  }|dvst        d       	 t        |d      | _        | j                  dk(  r	d| _        n| j                  | _
        d| _        n{| j                  dk(  r| j                   syt        t        | j                         | j                        }t        | j                   d|       }| j                   d|= | xj                  |z  c_
        | j                  r| j                  |       | j                  dk(  rd| _        n| j                  dk(  r0t        | j                         dk  ry| j                   dd= d| _        n| j                  dk(  rx| j                   j                  d      }|dk(  ryt        | j                   d|       }| j                   d|dz   = |s+d| _        d| _        | j                   r| j!                          y| j                   ry# t        $ r t        d      w xY w)z Parse chunked transfer encoding.r_   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   rw   crlfr   T)rC   rO   r   r   r9   r   r7   r   rP   r   rQ   r   r   r@   rB   rL   rA   )	ra   r   	size_line	semicolon	chunk_extcto_readr   r   s	            r   rv   z"PythonProtocol._parse_chunked_body  s   ll  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 llh g " A*+?@@As   J* *J?c                 r    |sydt        |      cxk  rdk  sy y|D ]  }|dv s y | j                  |      S )z>Check if method is valid token with conventional restrictions.Fr      s   abcdefghijklmnopqrstuvwxyz#)r   r   )ra   rE   r  s      r   r   zPythonProtocol._is_valid_method  sM    CK%2% &A22  ##F++r   c                 <    |sy|D ]  }|dk  s|dkD  r y|dv s y y)z6Check if data contains only RFC 9110 token characters.F!   ~   s   "(),/:;<=>?@[\]{}"Tr   )ra   rw   r  s      r   r   zPythonProtocol._is_valid_token  s3    A4x1t8**  r   c                 "    d|v xs
 d|v xs d|v S )z&Check for NUL, CR, LF in header value.    r     
r   )ra   r   s     r   r   z(PythonProtocol._has_invalid_header_chars  s    %C5E>CUe^Cr   )NNNNNN  d   r  FFr\   )r   r   r	   r
   	__slots__rm   rx   propertyr{   r~   r   rr   r   r   rs   rt   r   ru   rv   r   r   r   r   r   r   r;   r;   ]   s    I     !%*/+09"v< ) )(,2;z`D3j*3Xm,^*Vp,
Dr   r;   c                   8    e Zd ZdZdZd Zedd       Zd Zd Z	y)	CallbackRequestzxRequest object built from callback parser state.

    Works with both H1CProtocol (C extension) and PythonProtocol.
    rE   urirF   queryfragmentr   rH   headers_bytesschemeraw_pathrI   rp   
must_closer{   _expect_100_continuec                     d | _         d | _        d | _        d | _        d | _        d | _        g | _        g | _        d| _        d| _	        d| _
        d| _        d| _        d | _        d| _        y )Nhttpr   r   Fr  rz   s    r   rm   zCallbackRequest.__init__  so    	
#' $)!r   c                    ddl m}  |        }|j                  j                  d      |_        |j                  }d|v rQ|j                  dd      \  }}||_         ||      j                  dd      |_        |j                  d	      |_        n,||_         ||      j                  dd      |_        d
|_        |j                  d	      |_        d
|_	        |j                  |_        t        t        |dd      xs |j                        |_        |j                  D 	cg c]5  \  }}	|j                  d	      j!                         |	j                  d	      f7 c}	}|_        |rdnd|_        |j$                  xs d|_        |j&                  |_        |j*                   |_        |j                  D ](  \  }
}|
dk(  s|j/                         dk(  s d|_         |S  |S c c}	}w )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httpsr!  s   expects   100-continueT)urllib.parser#  rE   r   rF   r   r  r  r  r  rG   r   listgetattrrH   r  r   r  rI   rJ   rp   rK   r  r   r  )clsparseris_sslr#  reqraw_url	path_part
query_partnr   r   r   s               r   from_parserzCallbackRequest.from_parser*  s    	2e]]))'2
 ++7?$+MM$$:!Iz$CL'	299')9TCH")))4CI"CL'077	7RCHCI..+))
 !!F!X&..Y 
&1 XXi &&(!((9*=>&

 !'WF
#227a''#555 ">>KD%y U[[]o%E+/(
 *
 
!
s   !:G 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
CONNECTIONz 	closez
keep-aliveFr   )r  rH   r   r   r   )ra   r   r   r   s       r   should_closezCallbackRequest.should_closec  se    ??<<KD%|#KKM''.<,&  ( ||v%%r   c                 ^    |j                         }| j                  D ]  \  }}||k(  s|c S  y)z.Get a header value by name (case-insensitive).N)r   rH   )ra   r   hr   s       r   
get_headerzCallbackRequest.get_headerq  s0    zz|LLDAqDy ! r   N)F)
r   r   r	   r
   r  rm   classmethodr6  r:  r=  r   r   r   r  r    s2    
I*" 6 6p&r   r  )r
   r   enumr   	Exceptionr   r   r   r   r   r   r!   r%   r'   r)   r,   r/   r1   r3   r5   r7   r9   r;   r  r   r   r   <module>rA     s   
  1 1*z *, ,
 F w  1z 16* 6   :    
  J  /
 /;z ;0J 0l
D l
D^k kr   