
    [iq                     |   d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZmZ ddlmZ ddlmZ ddlmZ  G d d	      Zd
 Zd Zi ZdZdada ed      D  ci c]  } | | ddj9                  d       c} ZdZ G d d      Zd Z d Z! G d d      Z" G d d      Z# G d dejH                        Z%yc c} w )z
ASGI protocol handler for gunicorn.

Implements asyncio.Protocol to handle HTTP/1.x and HTTP/2 connections
and dispatch to ASGI applications.
    N)AsyncUnreader)PythonProtocolCallbackRequest
ParseErrorLimitRequestLineLimitRequestHeadersInvalidChunkExtension)AsyncUWSGIRequest)
NoMoreData)UWSGIParseExceptionc                       e Zd ZdZdZd Zy)_RequestTimezLightweight request time container compatible with logging atoms.

    Uses time.monotonic() elapsed seconds instead of datetime.now() syscalls.
    Provides .seconds and .microseconds attributes for glogging.py compatibility.
    )secondsmicrosecondsc                 d    t        |      | _        t        || j                  z
  dz        | _        y )Ni@B )intr   r   )selfelapseds     g/var/www/html/userprofiledev.eatanceapp.com/venv/lib/python3.12/site-packages/gunicorn/asgi/protocol.py__init__z_RequestTime.__init__$   s(    7|4<<!79 DE    N)__name__
__module____qualname____doc__	__slots__r    r   r   r   r      s     ,IFr   r   c                 &    | rt        | dd       S dS )zNormalize socket address to ASGI-compatible (host, port) tuple.

    ASGI spec requires server/client to be (host, port) tuples.
    IPv6 sockets return 4-tuples (host, port, flowinfo, scope_id),
    so we extract just the first two elements.
    N   )tuple)sockaddrs    r   _normalize_sockaddrr"   )   s     #+5"144r   c                     t        | t              syd|v ry	 t        j                  | d         }|D ]  }||v s y y# t        $ r Y yw xY w)zCheck if peer address is in the trusted proxy list.

    Cached at connection start to avoid repeated IP parsing per request.
    F*Tr   )
isinstancer    	ipaddress
ip_address
ValueError)	peer_addr
allow_listnetworksipnetworks        r   _check_trusted_proxyr.   3   sd    
 i'
j!!)A,/ =    s   > 	A
	A
s   Server: gunicorn/asgi
r   g        i @  x
latin-1i   c                   8    e Zd ZdZdZd Zd Zd Zd Zd Z	d Z
y	)
FlowControlzManage transport-level write flow control.

    Blocks send() when transport buffer exceeds high water mark,
    preventing memory issues with large streaming responses.
    )
_transportread_pausedwrite_paused_is_writable_eventc                     || _         d| _        d| _        t        j                         | _        | j
                  j                          y NF)r4   r5   r6   asyncioEventr7   set)r   	transports     r   r   zFlowControl.__init__]   s9    # !")--/##%r   c                 T   K   | j                   j                          d{    y7 w)z!Wait until transport is writable.N)r7   waitr   s    r   drainzFlowControl.draind   s     %%**,,,s   (&(c                 `    | j                   s"d| _         | j                  j                          y y NT)r5   r4   pause_readingr@   s    r   rD   zFlowControl.pause_readingh   s(    #DOO))+  r   c                 `    | j                   r"d| _         | j                  j                          y y r9   )r5   r4   resume_readingr@   s    r   rF   zFlowControl.resume_readingm   s(    $DOO**, r   c                 `    | j                   s"d| _         | j                  j                          y y rC   )r6   r7   clearr@   s    r   pause_writingzFlowControl.pause_writingr   s*       $D##))+ !r   c                 `    | j                   r"d| _         | j                  j                          y y r9   )r6   r7   r<   r@   s    r   resume_writingzFlowControl.resume_writingw   s*     %D##'') r   N)r   r   r   r   r   r   rA   rD   rF   rI   rK   r   r   r   r3   r3   U   s-    
 TI&-,
-
,
*r   r3   c                      t        j                          } | t        z
  dk\  r$ddlm} d |d       dj	                  d      a| at
        S )	z1Get cached Date header, updating once per second.      ?r   )
formatdatezDate: T)usegmtr0   r1   )time_cached_date_timeemail.utilsrN   encode_cached_date_header)nowrN   s     r   _get_cached_date_headerrV   }   sL     ))+C
#%* &z'>&?tDKKIVr   c           	          | |f}|t         vr-d| d    d| d    d| d| d	}|j                  d      t         |<   t         |   S )zGet cached status line bytes.HTTP/r   .    r0   r1   )_CACHED_STATUS_LINESrS   )versionstatusreasonkeylines        r   _get_cached_status_linerb      s\    F
C
&&wqzl!GAJ<q&F$(KK	$:S!$$r   c                       e Zd ZdZd Zy)ASGIResponseInfoz;Simple container for ASGI response info for access logging.c                     || _         || _        g | _        |D ]d  \  }}t        |t              r|j                  d      }t        |t              r|j                  d      }| j                  j                  ||f       f y )Nr1   )r^   sentheadersr%   bytesdecodeappend)r   r^   rg   rf   namevalues         r   r   zASGIResponseInfo.__init__   sk    	"KD%$&{{9-%'Y/LLu. #r   N)r   r   r   r   r   r   r   r   rd   rd      s
    E
/r   rd   c                   J    e 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)BodyReceiverzBody receiver for callback-based parsers.

    Body chunks are fed directly via the feed() method from parser callbacks.
    Uses Future-based waiting for efficient async receive().
    )_chunks	_complete_body_finished_closed_waiterrequestprotocolc                 f    || _         || _        g | _        d| _        d| _        d| _        d | _        y r9   )rt   ru   ro   rp   rq   rr   rs   )r   rt   ru   s      r   r   zBodyReceiver.__init__   s4     #r   c                 `    |r,| j                   j                  |       | j                          yy)z7Feed a body chunk directly (called by parser callback).N)ro   rj   _wake_waiterr   chunks     r   feedzBodyReceiver.feed   s(    LL& r   c                 2    d| _         | j                          y)z1Mark body as complete (called when message ends).TN)rp   rx   r@   s    r   set_completezBodyReceiver.set_complete   s    r   c                 2    d| _         | j                          y)z%Signal that connection has been lost.TN)rr   rx   r@   s    r   signal_disconnectzBodyReceiver.signal_disconnect   s    r   c                     | j                   7| j                   j                         s| j                   j                  d       yyy)z#Wake up any pending receive() call.N)rs   done
set_resultr@   s    r   rx   zBodyReceiver._wake_waiter   s6    <<#DLL,=,=,?LL##D) -@#r   c                   K   | j                   s| j                  rddiS | j                  r| j                         S | j                  rd| _        ddddS | j
                  j                  dk(  r*| j
                  j                  sd| _        d| _        ddddS | j                  j                   rd| _         ddiS 	 | j                          d	{    | j                         S 7 # t        j                  $ r ddicY S w xY ww)
z:ASGI receive callable - returns body chunks or disconnect.typehttp.disconnectThttp.requestr   Fr   body	more_bodyr   N)rr   rq   ro   
_pop_chunkrp   rt   content_lengthchunkedru   _wait_for_data_build_receive_resultr:   CancelledErrorr@   s    r   receivezBodyReceiver.receive   s      <<4..-.. <<??$$ >>"&D*CeLL <<&&!+DLL4H4H!DN"&D*CeLL ==  DL-..	/%%'''--// (%% 	/-..	/s<   B6D 9C# C!C#  D !C# #C=:D <C==D c                     | j                   j                  d      }t        | j                         xs | j                   }|sd| _        d||dS )z/Pop a chunk and return the appropriate message.r   Tr   r   )ro   popboolrp   rq   )r   rz   mores      r   r   zBodyReceiver._pop_chunk   sH      #DLL!7%7"&D&DIIr   c                 t    | j                   rddiS | j                  r| j                         S d| _        ddddS )z,Build receive result after waiting for data.r   r   Tr   r   Fr   )rr   ro   r   rq   r@   s    r   r   z"BodyReceiver._build_receive_result   s@    <<-..<<??$$ #&%HHr   c                 X  K   | j                   s| j                  s| j                  ryt        j                         }|j                         | _        	 t        j                  | j                  d       d{    d| _        y7 # t        j                  $ r Y w xY w# d| _        w xY ww)z*Wait for body data to arrive via callback.N      >@timeout)	ro   rp   rr   r:   get_event_loopcreate_futurers   wait_forTimeoutError)r   loops     r   r   zBodyReceiver._wait_for_data   s     <<4>>T\\ %%'))+	 ""4<<>>>  DL	 ?## 		  DLsH   AB*$B 6B7B ;B*B BB BB 	B''B*N)r   r   r   r   r   r   r{   r}   r   rx   r   r   r   r   r   r   r   rn   rn      s>    (I 

*
/BJI r   rn   c                      e Zd ZdZdZdZdZdZ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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&d+d"Z'd# Z(d$ Z)d% Z*d& Z+d' Z,d( Z-d) Z.d* Z/y),ASGIProtocolzHTTP/1.1 protocol handler for ASGI applications.

    Handles connection lifecycle, request parsing, and ASGI app invocation.
    Uses callback-based parsing (H1CProtocol/PythonProtocol) for efficient
    incremental parsing in data_received().
    NFc                 f   || _         |j                  | _        |j                  | _        |j                  | _        d | _        d | _        d | _        d | _        d| _	        d| _
        d | _        d | _        d| _        d| _        d | _        d | _        d | _        d | _        d| _        d | _        d | _        y )Nr   Fi   )workercfglogasgiappr=   readerwriter_task	req_countrr   _body_receiver_response_buffer_reading_paused_max_buffer_size_keepalive_handle_callback_parser_request_ready_current_request_is_ssl_flow_control
_websocket)r   r   s     r   r   zASGIProtocol.__init__   s    ::::;;
 " !%  % ) "& !%" $ " r   c                    || _         | j                  xj                  dz  c_        |j                  d      }|rut	        |d      ri|j                         }|dk(  rTt        j                         | _        | j                  j                  j                  | j                  ||            | _        y|du| _        || _        t        |      | _        |j#                  t$               t        j&                         | _        | j+                          | j                  j                  j                  | j-                               | _        y)z(Called when a connection is established.rZ   
ssl_objectselected_alpn_protocolh2N)high)r=   r   nr_connsget_extra_infohasattrr   r:   StreamReaderr   r   create_task_handle_http2_connectionr   r   r   r3   r   set_write_buffer_limitsHIGH_WATER_LIMITr;   r   _setup_callback_parser_handle_connection)r   r=   r   alpns       r   connection_madezASGIProtocol.connection_madeF  s
   "! --l;
'*.FG446Dt|%224![[--9911)ZH
  "- )3))/?)@ &mmo##%[[%%11$2I2I2KL
r   c                    | j                   H	 ddl}ddlm} d| _         || _        t	        |d      | _        t        |dd      | _        | j                   S | j                   S # t        $ r d| _         d| _        Y | j                   S w xY w)z:Check if H1CProtocol is available (cached at class level).Nr   )H1CProtocolTr   r	   F)	_h1c_availablegunicorn_h1cr   _h1c_protocol_classr   _h1c_has_limitsgetattr_h1c_invalid_chunk_extensionImportError)clsr   r   s      r   _check_h1c_protocol_availablez*ASGIProtocol._check_h1c_protocol_availabled  s     %,#4%)"*5'&-l<N&O#3: "9440 !!!s!!!  ,%*"&+#!!!,s   ;A! !BB)permit_obsolete_foldingstrip_header_spacesc           
      \   t        | j                  dd      }g }| j                  D ]+  }t        | j                  |d      s|j                  |       - |dk(  rt        }n|dk(  rf| j                         st        d      t        j                  st        d      |rt        dd	j                  |      z        t        j                  }n9| j                         r#t        j                  r|st        j                  }nt        }| j                  j                  }|d
k(  r|t        k7  rd} || j                  | j                  | j                  || j                  j                  | j                  j                   | j                  j"                  | j                  j$                        | _        y)aC  Create callback parser based on http_parser setting.

        Parser selection:
        - auto: Use H1CProtocol if available (>= 0.4.1) and no incompatible flags, else PythonProtocol
        - fast: Require H1CProtocol >= 0.4.1 (error if unavailable or incompatible flags)
        - python: Use PythonProtocol only
        http_parserautoFpythonfastz,gunicorn_h1c required for http_parser='fast'zigunicorn_h1c >= 0.4.1 required for http_parser='fast'. Please upgrade: pip install --upgrade gunicorn_h1czqhttp_parser='fast' is incompatible with compatibility flags: %s. Use http_parser='python' or disable these flags.z, r   i   )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_versionN)r   r   _FAST_PARSER_INCOMPATIBLE_FLAGSrj   r   r   RuntimeErrorr   r   joinr   r   _on_headers_complete_on_body_on_message_completer   r   r   r   r   )r   parser_settingincompatibleflagparser_classr   s         r   r   z#ASGIProtocol._setup_callback_parser~  sy    !=&A 88Dtxxu-##D) 9 X%)Lv%557"#QRR//"I  "Gii-. 
 (;;L224 00+??- "XX88"|~'E!, !- $ 9 9MM $ 9 91!%!>!>%)XX%F%F.2hh.X.X/3xx/Z/Z	!
r   c                    t        j                  | j                  | j                        | _        t        | j                  |       | _        | j                  r| j                  j                          | j                  j                  dk(  S )z'Callback: request headers are complete.)is_ssls   HEAD)
r   from_parserr   r   r   rn   r   r   r<   methodr@   s    r   r   z!ASGIProtocol._on_headers_complete  ss     !0 ; ;!!$,,!

 +4+@+@$G ##% $$++w66r   c                 T    | j                   r| j                   j                  |       yy)z#Callback: received body data chunk.N)r   r{   ry   s     r   r   zASGIProtocol._on_body  s$    $$U+ r   c                 R    | j                   r| j                   j                          yy)z$Callback: request is fully received.N)r   r}   r@   s    r   r   z!ASGIProtocol._on_message_complete  s"    ,,. r   c                    | j                   r| j                   j                  |       y| j                  r| j                  j                  |       n(| j                  r	 | j                  j	                  |       | j                   s"| j#                         r| j%                          yyy# t
        $ r5}| j                  dt        |             | j                          Y d}~yd}~wt        $ r5}| j                  dt        |             | j                          Y d}~yd}~wt        $ r5}| j                  dt        |             | j                          Y d}~yd}~wt        $ r5}| j                  dt        |             | j                          Y d}~yd}~wt        $ rT}t        j                  }|<t        ||      r0| j                  dt        |             | j                          Y d}~y d}~ww xY w)z/Called when data is received on the connection.N  i    )r   	feed_datar   r   r{   r   _send_error_responsestr_close_transportr   r	   r   	Exceptionr   r   r%   r   _is_buffer_full_pause_reading)r   dataeh1c_excs       r   data_receivedzASGIProtocol.data_received  s   ??OO%%d+;;KK!!$'""%%**408 ##(<(<(>! )?#7 $ ))#s1v6%%'& ))#s1v6%%'( ))#s1v6%%' ))#s1v6%%' &CC&:a+A--c3q6:))+sO   B( (	G51+C!!G5-+DG5)+EG5%+FG5!A	G0/G00G5c                     | j                   rBt        | j                   d      r,t        | j                   j                        | j                  kD  S y)z/Check if internal buffer is full (HTTP/2 only)._bufferF)r   r   lenr   r   r@   s    r   r   zASGIProtocol._is_buffer_full  s9    ;;74;;	:t{{**+d.C.CCCr   c                     | j                   s0| j                  r#d| _         	 | j                  j                          yyy# t        t        f$ r Y yw xY w)z1Pause reading from transport due to backpressure.TN)r   r=   rD   AttributeErrorr   r@   s    r   r   zASGIProtocol._pause_reading  sO    ###'D ,,. )7# #L1    > AAc                     | j                   r0| j                  r#d| _         	 | j                  j                          yyy# t        t        f$ r Y yw xY w)zResume reading from transport.FN)r   r=   rF   r  r   r@   s    r   _resume_readingzASGIProtocol._resume_reading  sO    DNN#(D --/ %3 #L1 r  c                     | j                   r| j                   j                          | j                  j                  }|dkD  r6| j                  j
                  j                  || j                        | _         yy)z6Arm keepalive timeout timer after response completion.r   N)r   cancelr   	keepaliver   r   
call_later_keepalive_timeout)r   keepalive_timeouts     r   _arm_keepalive_timerz!ASGIProtocol._arm_keepalive_timer  sb    !!""))+ HH..q %)[[%5%5%@%@!4#:#:&D" !r   c                 `    | j                   r"| j                   j                          d| _         yy)z0Cancel keepalive timer when new request arrives.N)r   r  r@   s    r   _cancel_keepalive_timerz$ASGIProtocol._cancel_keepalive_timer   s*    !!""))+%)D" "r   c                 $    | j                          y)z&Called when keepalive timeout expires.N)r   r@   s    r   r  zASGIProtocol._keepalive_timeout&  s    r   c                    | j                   ryd| _         | j                  xj                  dz  c_        | j                          | j                  r| j                  j                          | j                  r| j                  j                          | j                  | j                  j                          | j                  r| j                  j                         sht        | j                  dd      }|dkD  r1| j                  j                  j                  || j                         y| j                  j!                          yyy)a  Called when the connection is lost or closed.

        Instead of immediately cancelling the task, we signal a disconnect
        event and send an http.disconnect message to the receive queue.
        This allows the ASGI app to clean up resources (like database
        connections) gracefully before the task is cancelled.

        See: https://github.com/benoitc/gunicorn/issues/3484
        NTrZ   asgi_disconnect_grace_period   r   )rr   r   r   r  r   feed_eofr   r   r   r   r   r   r   r   r
  _cancel_task_if_pendingr  )r   excgrace_periods      r   connection_lostzASGIProtocol.connection_lost*  s     <<! 	$$&;;KK  " ??OO$$& *113 ::djjoo/"488-KQOLa  ++ 00 

!!# 0:r   c                     | j                   r6| j                   j                         s| j                   j                          yyy)z9Cancel the task if it's still pending after grace period.N)r   r   r  r@   s    r   r  z$ASGIProtocol._cancel_task_if_pendingU  s-    ::djjoo/JJ 0:r   c                 R    | j                   r| j                   j                          yy)z>Called by transport when write buffer exceeds high water mark.N)r   rI   r@   s    r   rI   zASGIProtocol.pause_writingZ  s"    ,,. r   c                 R    | j                   r| j                   j                          yy)zBCalled by transport when write buffer drains below low water mark.N)r   rK   r@   s    r   rK   zASGIProtocol.resume_writing_  s"    --/ r   c                 >   	 | j                   j                  |       y# t        $ re}|j                  t        j                  t        j
                  t        j                  fvr | j                  j                  d       Y d}~yY d}~yd}~wt        t        f$ r Y yw xY w)ax  Write data to transport, handling connection errors gracefully.

        Catches exceptions that occur when the client has disconnected:
        - OSError with errno EPIPE, ECONNRESET, ENOTCONN
        - RuntimeError when transport is closing/closed
        - AttributeError when transport is None

        These are silently ignored since the client is already gone.
        zSocket error writing response.N)r=   writeOSErrorerrnoEPIPE
ECONNRESETENOTCONNr   	exceptionr   r  )r   r   r   s      r   _safe_writezASGIProtocol._safe_writed  sw    	NN  & 	Ewwu{{E,<,<ennMM""#CDD Nn- 		s    	BABBBc                 2  K   	 | j                   j                  d      }| j                   j                  d      }t        | j                  dd      }|dk(  r,| j	                  ||       d{    	 | j                          y| j                  s| xj                  dz  c_        | j                          | j                  j                         s#	 | j                  j                          d{    | j                  s| j                  n{| j                  }| j                  |      r| j!                  |||       d{    nA| j#                  |||       d{   }| j$                  xj&                  dz  c_        | j$                  j&                  | j$                  j(                  k\  r.| j*                  j-                  d       d	| j$                  _        d	}|r| j$                  j.                  sn| j                  j0                  sn|| j3                          | j4                  r| j4                  j7                          d| _        d| _        | j                  j;                          | j=                          | j                  s| j                          y7 ,7 # t        j                  $ r Y ,w xY w7 x7 ^# t        j                  $ r Y Kt>        $ r&}| j*                  jA                  d
|       Y d}~td}~ww xY w# | j                          w xY ww)aB  Main request handling loop using callback-based parser.

        Uses synchronous parsing in data_received(), avoiding the async
        overhead of pull-based parsing. The parser fires callbacks when
        headers and body data are available, and this loop waits on
        events rather than actively parsing.
        peernamesocknameru   httpuwsgiNrZ   ,Autorestarting worker after current request.FzError handling connection: %s)!r=   r   r   r   _handle_connection_uwsgir   rr   r   r  r   is_setr?   r:   r   r   _is_websocket_upgrade_handle_websocket_handle_http_requestr   nrmax_requestsr   infoaliver	  r  r   resetr   rH   r  r   r#  )r   r&  r'  protocol_typert   r	  r   s          r   r   zASGIProtocol._handle_connectionw  s    I	$~~44Z@H~~44Z@H $DHHj&AM'33HhGGGB !!# ll!#,,. **113"1166888 <<4#8#8#@// --g600(HMMM #'";";Xx# 	
 !# ;;>>T[[%=%==HHMM"PQ(-DKK% %I (9(9 xx)) $$& (())//1 )-%&*###))+ ))+q ll~ !!#E H 9"11  NF %% 	 	CHH>BB	C !!#s   LA'J< +J,J< 1LAJ< J ,J-J 1AJ< >J6?J< J9D(J< LJ< J J30J< 2J33J< 9J< <K?L K?K:5L :K??L LLc                   K   t        | j                        }| j                  sc| xj                  dz  c_        	 t	        j
                  | j                  ||| j                         d{   }| j                  |      r| j                  |||       d{    y| j                  |||       d{   }| j                  xj                  dz  c_        | j                  j                  | j                  j                   k\  r.| j                  j#                  d       d| j                  _        d}|r| j                  j$                  sy| j                  j&                  sy|j)                          d{    | j                  sbyy7 # t        $ r Y yt        $ r&}| j                  j                  d|       Y d}~yd}~ww xY w7 27 7 Yw)z0Handle uWSGI protocol connections (legacy path).rZ   NzuWSGI parse error: %sr*  F)r   r   rr   r   r
   parser   r   r   r   debugr-  r.  r/  r   r0  r1  r2  r3  r	  
drain_body)r   r&  r'  unreaderrt   r   r	  s          r   r+  z%ASGIProtocol._handle_connection_uwsgi  sz     -,,NNaN 1 7 7HHNN	!  ))'2,,WhIII #778 I
 KKNNaN {{~~!9!99LM$)!!	DKK$5$588%%$$&&&S ,,  & 6: J& 's   8G/F *F	+F /'GGG2G3CG4G5GG	F 	GGGG ;G GGGGc                     |j                   dk7  ryd}d}|j                  D ]1  \  }}|dk(  r|j                         }|dk(  s"|j                         }3 |dk(  xr |xr d|v S )a	  Check if request is a WebSocket upgrade.

        Per RFC 6455 Section 4.1, the opening handshake requires:
        - HTTP method MUST be GET
        - Upgrade header MUST be "websocket" (case-insensitive)
        - Connection header MUST contain "Upgrade"
        GETFNUPGRADE
CONNECTION	websocketupgrade)r   rg   lower)r   rt   r@  
connectionrk   rl   s         r   r-  z"ASGIProtocol._is_websocket_upgrade  sq     >>U"
"??KD%y ++-%"[[]
	 +
 +%P*Pj9PPr   c                    K   ddl m} d| _        | j                  |||      } || j                  || j
                  | j                        }|| _        |j                          d{    y7 w)z!Handle WebSocket upgrade request.r   )WebSocketProtocolN)	gunicorn.asgi.websocketrD  r   _build_websocket_scoper=   r   r   r   run)r   rt   r'  r&  rD  scopews_protocols          r   r.  zASGIProtocol._handle_websocket  s_     = !%++GXxH'NNE488TXX

 &oos   A$A.&A,'A.c           	      "	   K    j                  ||      }ddddd _        dg d j                  } f	d} j                  j                  }	 t        j                         } j                  j                   j                          j                  ||j                  |       d{    s j                  dd       dd _        	 t!        t        j                         |z
        }	|r? j#                  ||      }
t%              } j                  j'                  ||
|	       nd}
d} j                  j)                   j                  |
|       j/                         ry j                  j0                  xr  j                  j2                  S 7 # t        j                  $ r  j                  j                  d       Y d _        	 t!        t        j                         z
        }	|r? j#                  ||      }
t%              } j                  j'                  ||
|	       nd}
d} j                  j)                   j                  |
|       y# t*        $ r  j                  j-                  d       Y yw xY wt*        $ r  j                  j-                  d	       s j                  dd       dY d _        	 t!        t        j                         z
        }	|r? j#                  ||      }
t%              } j                  j'                  ||
|	       nd}
d} j                  j)                   j                  |
|       y# t*        $ r  j                  j-                  d       Y yw xY ww xY w# t*        $ r  j                  j-                  d       Y Uw xY w# d _        	 t!        t        j                         z
        }	|r? j#                  ||      }
t%              } j                  j'                  ||
|	       nd}
d} j                  j)                   j                  |
|       w # t*        $ r  j                  j-                  d       Y w w xY wxY ww)
zHandle a single HTTP request.FN  r   c                   	K   j                   ry | d   }|dk(  r7| j                  d      }| j                  dg       }j                  ||       y |dk(  rort        d      y d| d   | j                  dg       
t	        d 
D              }|s j
                  d	k\  rdt        
      d
gz   
j                  
       y |dk(  rst        d      y 	rt        d      y | j                  dd      }| j                  dd      }|rOj                  |       t        |      z  j                  r"j                  j                          d {    |swrDj                  r&j                  j                  dz          d _        n@j                  d       n.j                  r"j                  j                         d _        d	y y y 7 w)Nr   http.response.informationalr^   rg   http.response.startResponse already startedTc              3      K   | ]o  \  }}t        |t              r|j                         n|j                         d k(  xs3 t        |t              r|j                         n|j                         dk(   q yw)s   content-lengthzcontent-lengthN)r%   r   rA  ).0rk   _s      r   	<genexpr>zBASGIProtocol._handle_http_request.<locals>.send.<locals>.<genexpr>M  sg      ) $4a &0c%:TZZ\

Qbb e(24(=

4::<Tdde#3s   A5A7rZ   rZ   )s   transfer-encodings   chunkedhttp.response.bodyResponse not startedResponse already completer   r   r   F)r   s   0

)rr   get_send_informationalr   anyr]   list_send_response_start
_send_bodyr  r   rA   r   r$  )messagemsg_typeinfo_statusinfo_headershas_content_lengthr   r   exc_to_raisert   response_completeresponse_headersresponse_sentresponse_startedresponse_statusr   use_chunkeds          r   sendz/ASGIProtocol._handle_http_request.<locals>.send2  s     ||vH88%kk(3&{{9b9((lGL00##/0J#KL#' ")("3#*;;y"#=  &) ) $4) &" *goo.G"&K'+,<'=Ac@d'd$))/;KWU11'#/0F#GL$#/0K#LL{{63/#KKU;	OOD+O>!SY.M))"0066888 "00 ,,T-B-B\-QR48D1 ,,\:..(()>)>?04-(,% !% 2  9s   EGGB GInternal Server Errorz'Request cancelled (client disconnected)Exception in post_request hookError in ASGI application)_build_http_scoper   r   r   access_log_enabledrP   	monotonicr   pre_requestr   r   r   r   r:   r   r8  r   _build_environrd   accesspost_requestr   r#  should_closer3  r	  )r   rt   r'  r&  rH  body_receiverrj  ro  request_startrequest_timeenvironresprc  rd  re  rf  rg  rh  ri  s   ``          @@@@@@@r   r/  z!ASGIProtocol._handle_http_request  s1    &&w(C ! !%  ++F	- F	-R "XX88(	E NN,MHH  g6((5-"7"7>>>'"" $))#/FG"% #'DE+DNN,<},LM%"11'8XNG+O=M}]DHHOOD'7LI"GD%%dkk7GTJ
 !{{  7TXX%7%77U ? %% 	HHNNDE #'DE+DNN,<},LM%"11'8XNG+O=M}]DHHOOD'7LI"GD%%dkk7GTJ E""#CDE+  	HH:;#))#/FG"% #'DE+DNN,<},LM%"11'8XNG+O=M}]DHHOOD'7LI"GD%%dkk7GTJ E""#CDE+	*  E""#CDE #'DE+DNN,<},LM%"11'8XNG+O=M}]DHHOOD'7LI"GD%%dkk7GTJ E""#CDEs   AR$AF3 >F1?F3 R%BN  2?R1F3 3.N!O "R*BI8 7R8$JRJR"9NO R$BM2 1R2$NRNRNO  $ORORRBQ"!R"$R	RR		RRc                 ,   t        |dd      }t        |t              rt        |      }nUg }|j                  D ]D  \  }}|j	                  |j                         j                  d      |j                  d      f       F t        |      }t        |      }	dddd|j                  d    d	|j                  d
    |j                  |j                  |j                  |j                  r|j                  nd|j                  r|j                  j                  d      nd| j                  j                  xs d|||	d}
t!        | j"                  d      r| j"                  j$                  |
d<   t!        |d      rd|j&                  |j(                  di|
d<   |
S )z*Build ASGI HTTP scope from parsed request.headers_bytesNr1   r(  3.02.4r]   spec_versionr   rY   rZ   r    r   r   http_versionr   schemepathraw_pathquery_string	root_pathrg   serverclientstatepriority_weighthttp.response.priorityweight
depends_on
extensions)r   r%   r[  rg   rj   rA  rS   r"   r]   r   r  r  r  queryr   r  r   r   r  r  priority_depends_on)r   rt   r'  r&  r|  rg   rk   rl   r  r  rH  s              r   rn  zASGIProtocol._build_http_scope  so     $?mT*=)GG&e

 3 3I >Y@WXY  / %X.$X.  %u=&q12!GOOA4F3GHnnnnLL,3,<,<((#?F}}GMM00;RU++1r
  4;;(![[..E'N 7-.(%55")"="=+#E, r   c           	         |j                   |j                  |j                  |j                  xs dd|j                  d    d|j                  d    |r|d   ndd}|j
                  D ]  \  }}d|j                  dd	      z   }|||<   ! |S )
z8Build minimal WSGI-like environ dict for access logging.r  rX   r   rY   rZ   -REQUEST_METHODRAW_URI	PATH_INFOQUERY_STRINGSERVER_PROTOCOLREMOTE_ADDRHTTP_rR  )r   urir  r  r]   rg   replacer   rt   r'  r&  ry  rk   rl   r`   s           r   rr  zASGIProtocol._build_environ  s     &nn{{ #MM/R!&wq'9&:!GOOA<N;OP*28A;
 #??KD%DLLc22C GCL + r   c                    g }|j                   D ]D  \  }}|j                  |j                         j                  d      |j                  d      f       F g }|j                   D ]8  \  }}|dk(  s|j	                  d      D cg c]  }|j                          }} n t        |      }	t        |      }
dddd|j                  d    d	|j                  d
    |j                  dk(  rdnd|j                  |j                  r|j                  nd|j                  r|j                  j                  d      nd| j                  j                  xs d||	|
|d}t        | j                  d      r| j                  j                   |d<   |S c c}w )z/Build ASGI WebSocket scope from parsed request.r1   zSEC-WEBSOCKET-PROTOCOL,r?  r}  r~  r  r   rY   rZ   httpswsswsr   r  )r   r   r  r  r  r  r  r  rg   r  r  subprotocolsr  )rg   rj   rA  rS   splitstripr"   r]   r  r  r  r  r   r  r   r   r  )r   rt   r'  r&  rg   rk   rl   r  sr  r  rH  s               r   rF  z#ASGIProtocol._build_websocket_scope  sm    "??KD%NNDJJL//	:ELL<STU + "??KD%//38;;s3CD3Ca	3CD +
 %X.$X.   %u=&q12!GOOA4F3GH&~~8edLL,3,<,<((#?F}}GMM00;RU++1r(
  4;;(![[..E'N3  Es   F	c           	         |j                   dk  ry| j                  |      }d|j                   d    d|j                   d    d| d| d	}|D ]R  \  }}t        |t              r|j	                  d	      }t        |t              r|j	                  d	      }|| d
| dz  }T |dz  }| j                  |j                  d	             y)ao  Send an informational response (1xx) such as 103 Early Hints.

        Args:
            status: HTTP status code (100-199)
            headers: List of (name, value) header tuples
            request: The parsed request object

        Note: Informational responses are only sent for HTTP/1.1 or later.
        HTTP/1.0 clients do not support 1xx responses.
        rT  NrX   r   rY   rZ   r[   r0   r1   z: )r]   _get_reason_phraser%   rh   ri   r$  rS   )r   r^   rg   rt   r_   responserk   rl   s           r   rY  z ASGIProtocol._send_informational  s     ??V#((07??1-.a0B/C1VHAfXUYZ"KD%$&{{9-%'Y/4&5'..H # 	F34r   c                    | j                  |      }t        |j                  ||      }|g}d}d}|D ]  \  }	}
t        |	t              r"|	j                         }|j                  |	       n?|	j                         j                  d      }|j                  |	j                  d             |j                  d       t        |
t              r|j                  |
       n |j                  |
j                  d             |j                  d       |dk(  rd}|dk(  sd} |s|j                  t               |s|j                  t                      |j                  d       dj                  |      | _        y	)
zSend HTTP response status and headers.

        Uses cached status lines and headers for common cases to avoid
        repeated string formatting and encoding.
        Fr1   s   :    
s   dateTs   serverr   N)r  rb   r]   r%   rh   rA  rj   rS   _CACHED_SERVER_HEADERrV   r   r   )r   r^   rg   rt   r_   status_linepartshas_date
has_serverrk   rl   
name_lowers               r   r\  z!ASGIProtocol._send_response_start.  s5    ((0-goovvN 
"KD%$&!ZZ\
T"!ZZ\00;
T[[34LL%'U#U\\)45LL! W$y(!
+ #0 LL./LL023W !$r   c                    |r|r@t        |      }t        j                  |      xs |ddj                  d      }||z   dz   }nd}| j                  r&| j                  | j                  |z          d| _        y|r| j                  |       yy| j                  r&| j                  | j                  |z          d| _        y|r| j                  |       yy)zySend response body chunk.

        Combines buffered headers with first body chunk for efficient write batching.
        r/   r0   r1   r  r   N)r  _CHUNK_PREFIXESrX  rS   r   r$  )r   r   r   sizeprefix
chunk_datas         r   r]  zASGIProtocol._send_body`  s    
  4y(,,T2Wao6L6LY6W#d]W4
 
 $$  !6!6!CD(,%  ,  $$  !6!6!=>(,%  & r   c                     |j                  d      }d| d| dt        |       d}| j                  |j                  d             | j                  |       y)zSend an error response.zutf-8z	HTTP/1.1 r[   z,
Content-Type: text/plain
Content-Length: z
Connection: close

r1   N)rS   r  r$  )r   r^   r^  r   r  s        r   r   z!ASGIProtocol._send_error_response}  sa    ~~g&xq	 *"4yk * 	 	34r   c                     i ddddddddd	d
dddddddddddddddddddddd d!d"i d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdB}|j                  |dC      S )Dz'Get HTTP reason phrase for status code.d   Continuee   zSwitching Protocolsg   zEarly Hints   OK   Created   Accepted   z
No Content   zPartial Contenti-  zMoved Permanentlyi.  Foundi/  z	See Otheri0  zNot Modifiedi3  zTemporary Redirecti4  zPermanent Redirectr   zBad Requesti  Unauthorizedi  	Forbiddeni  z	Not Foundi  zMethod Not Allowedi  zRequest Timeouti  Conflicti  Gonei  zLength Requiredi  zPayload Too Larger   zURI Too Longi  zUnsupported Media Typei  zUnprocessable Entityi  zToo Many RequestsrK  rk  i  zNot Implementedi  zBad Gatewayi  zService Unavailablei  zGateway TimeoutUnknown)rX  )r   r^   reasonss      r   r  zASGIProtocol._get_reason_phrase  s   "
"
&"
 "
 	"

 "
 "
 "
 ""
 $"
 "
 "
 "
 %"
 %"
 "
  !"
" #"
$ %"
& %'"
( ")"
* +"
, -"
. "/"
0 $1"
2 3"
4 )5"
6 '7"
8 $9"
: (;"
< "="
> ?"
@ &A"
B "C"
F {{69--r   c                    | j                   rd| j                  sW	 | j                   j                         r| j                   j                          | j                   j	                          d| _        yyy# t
        $ r Y w xY w)zClose the transport safely.

        Calls write_eof() first if supported to signal end of writing,
        which helps ensure buffered data is flushed before closing.
        TN)r=   rr   can_write_eof	write_eofcloser   r@   s    r   r   zASGIProtocol._close_transport  sj     >>$,,>>//1NN,,.$$&  DL #/>  s   AA2 2	A>=A>c           	        K   	 ddl m} |j                  d      }|j                  d      }| j                  }t	        j
                  |      }t	        j                  |||| j                  j                        } || j                  |||      }	|	j                          d{    |	| _        |	j                  s!| j                  j                  r
	 |	j                  d       d{   }
|
D ]D  }	 | j'                  ||	||       d{    |	j3                  |j,                  j.                         F | j                  xj4                  t7        |
      z  c_        | j                  j4                  | j                  j8                  k\  r-| j"                  j;                  d       d| j                  _        n$|	j                  s| j                  j                  r
t?        | d      r#	 | j                  jA                          d{    | jC                          y7 z7 7# t        j                  $ r Y t         $ r&}| j"                  j%                  d|       Y d}~d}~ww xY w7 _# t         $ rp}| j"                  j)                  d	       	 |	j+                  |j,                  j.                  d
t1        |             d{  7   n# t         $ r Y nw xY wY d}~d}~ww xY w# |	j3                  |j,                  j.                         w xY w# t        j<                  $ r Y Lt         $ r'}| j"                  j)                  d|       Y d}~vd}~ww xY w7 T# t         $ r Y ^w xY w# t?        | d      r4	 | j                  jA                          d{  7   n# t         $ r Y nw xY w| jC                          w xY ww)zHandle an HTTP/2 connection.r   )AsyncHTTP2Connectionr&  r'  NrM   r   zHTTP/2 receive error: %szError handling HTTP/2 requestrK  r*  FzHTTP/2 connection error: %s_h2_conn)"gunicorn.http2.async_connectionr  r   r   r:   StreamReaderProtocolStreamWriterr   r   r   initiate_connectionr  	is_closedr3  receive_datar   r   r   r8  _handle_http2_requestr#  
send_errorstream	stream_idr   cleanup_streamr0  r  r1  r2  r   r   r  r   )r   r=   r   r  r&  r'  r   ru   r   h2_connrequestsr   reqs                r   r   z%ASGIProtocol._handle_http2_connection  s)    C	$L //
;H //
;H [[F33F;H))8VT[[-=-=F
 +&&(G --///#DM ''DKK,=,=%,%9%9#%9%FFH $CE"88(H    ..szz/C/CD $" #h-/ ;;>>T[[%=%==HHMM"PQ(-DKK%A ''DKK,=,=N tZ(----/// !!#c 0  G++   HHNN#=qA % !**+JK!")"4"4 #

 4 4c3q6#    ) ! !!  ..szz/C/CD %% 	 	AHH<a@@	A
 0   tZ(----///  !!#s  OBL !H"/L H! 'H(H! ,L 2I+	I(
I+CL O(M MM 
OL H! !I%4L 7I%?I L  I%%L (I++	K$4K3K
KK
	K
	KKKKK'K$$K'''LL M$M, 'M/MM, MM, M 	M)%O(M))O,N>:NNNN>	N*'N>)N**N>>Oc                     g }|D ]h  \  }}t        |t              r|j                  d      }t        |t              r|j                  d      }|j                  |j	                         |f       j |S )z?Convert ASGI headers to HTTP/2 format (lowercase string names).r1   )r%   rh   ri   rj   rA  )r   rg   resultrk   rl   s        r   _convert_h2_headersz ASGIProtocol._convert_h2_headers  sc    "KD%$&{{9-%'Y/MM4::</0 # r   c           
         K   |j                   j                  j                  j                         j	                  |||      }dddddg ddfd} f
d} j
                  j                  }t        j                         }		  j                  j                   j                  |        j                  |||       d{    sj                  dd       d{    dns j                        }
dt              fg}|j!                  |
       j                  j                        rIj"                  j%                  |d	
       j%                  |d	
       j'                          d{    	 t-        t        j                         |	z
        }|r? j/                  |||      }t1              } j
                  j3                  ||||       nd}d} j                  j5                   j                  |||       y7 P7 27 # t(        $ r>  j
                  j+                  d       sj                  dd       d{  7   dY w xY w# t(        $ r  j
                  j+                  d       Y yw xY w# 	 t-        t        j                         |	z
        }|r? j/                  |||      }t1              } j
                  j3                  ||||       nd}d} j                  j5                   j                  |||       w # t(        $ r  j
                  j+                  d       Y w w xY wxY ww)zHandle a single HTTP/2 request with streaming support.

        Streams both request and response body chunks immediately,
        avoiding buffering entire uploads and enabling SSE, streaming
        downloads, and other real-time use cases.
        FNrK  r   c                    K   j                   j                  dk(  rddiS s0j                  r$j                  sdj	                         } d| ddS 	 t        j                  j                         d	       d {   }|ddd
ddS j                  rdd|j                   dS 7 -# t
        j                  $ r ddicY S w xY ww)NCLOSEDr   r   Tr   Fr   r   r   r   )
r  rk   request_complete_body_chunksget_request_bodyr:   r   read_body_chunkr   _body_complete)r   rz   body_receivedr  s     r   r   z3ASGIProtocol._handle_http2_request.<locals>.receive)  s     ~!2!2h!> 122 !V%<%<VEXEX $..0* !& 3%..**,   } $*!&  $$ $ '!'!6!66 % '' 3 1223s<   AC(B. >B,?B. )C,B. .CCCCc                 N  
K   | d   }|dk(  rP| j                  d      }| j                  dg       }j                  |      }j                  ||       d {    y |dk(  r(rt        d      y d| d   | j                  dg       y |dk(  r7st        d	      y rt        d
      y | j                  dd      }| j                  dd      }sj                        }dt	              fg}|j                  |       j                  j                        }|t        d      y j                  j                  |d       |j                  |d       j                          d {    d|r+j                  ||        d {    t        |      z  |s!|sj                  dd       d {    dy y |dk(  rLst        d      y | j                  dg       }	j                  |	      }
j                  |
       d {    y y 7 7 7 7 a7 w)Nr   rM  r^   rg   rN  rO  TrU  rV  rW  r   r   r   F:statuszStream closed
end_streamhttp.response.trailersz)Cannot send trailers before body complete)rX  r  send_informationalr   r   extendstreamsr  send_headers_send_pending_data	send_datar  send_trailers)r^  r_  r`  ra  rg   r   r   response_hdrsr  trailer_headerstrailersrc  r  headers_sentrd  re  rf  rg  rh  r   r  s              r   rj  z0ASGIProtocol._handle_http2_request.<locals>.sendT  sd     vH88%kk(3&{{9b922<@00KQQQ00##/0J#KL#' ")("3#*;;y"#=  11'#/0F#GL$#/0K#LL{{63/#KKU;	 $"667GHG&/_1E%F$GM!((1 %__00;F~'3O'DOO00MV[0\''%'H!44666#'L !++ItI+VVV!SY.M %//	34/PPP(,%	 ! 55(#/0[#\L")++i"<33OD++Ix@@@ 6e RH 7
 W Q As\   AH%HDH%0H1 H%H-H%?H! AH%H#H%H%H%!H%#H%rk  r  Tr  rm  rl  )r  r  r  rX  _build_http2_scoper   ro  rP   rp  r   rq  r   r   r  r  r   r  r  r  r  r   r#  r   _build_http2_environrd   rs  rt  )r   rt   r  r'  r&  rH  r   rj  ro  rw  rg   r  rx  ry  rz  r  rc  r  rd  re  rf  rg  rh  r  r  s   ` `            @@@@@@@@@@r   r  z"ASGIProtocol._handle_http2_request  s5     NN,,	$$Y/''8D ! )	VC	A C	AL "XX88(,	EHH  g6((5'4000'"" $((C9PQQQ"% "223CD"+S-A!B C$$W- ,,Y7OO00MVZ0[''$'G!44666E+DNN,<},LM%"778TG+')9=D HHOOD'7LI"GD%%dkk7GTJQ 1 R 7 	&HH:;((C9PQQQ"%		&&  E""#CDEE+DNN,<},LM%"778TG+')9=D HHOOD'7LI"GD%%dkk7GTJ E""#CDEs   BM'"<H6 H. H6 ?H1 BH6 H4H6  BJ  -M'.H6 1H6 4H6 6<I=2I53I=:J* <I==J*  $J'$M'&J''M'*M$,BL:9M$:$M!M$ M!!M$$M'c                    g }|j                   D ]D  \  }}|j                  |j                         j                  d      |j                  d      f       F t	        |      }t	        |      }ddddd|j
                  |j                  |j                  t        |dd      xs) |j                  r|j                  j                  d      nd	|j                  r|j                  j                  d      nd	| j                  j                  xs d
|||d}	t        | j                  d      r| j                  j                  |	d<   i }
t        |d      r|j                  |j                   d|
d<   i |
d<   |
|	d<   |	S )z*Build ASGI HTTP scope from HTTP/2 request.r1   r(  r}  r~  r  2r  Nr   r  r  r  r  r  r  r  r  )rg   rj   rA  rS   r"   r   r  r  r   r  r   r  r   r   r  r  r  )r   rt   r'  r&  rg   rk   rl   r  r  rH  r  s              r   r   zASGIProtocol._build_http2_scope  s_   "??KD%NN

##I.Y'  + %X.$X.  %u=nnnnLLT:wahamamw||?R?RS\?]sv?F}}GMM00;RU++1r
 4;;(![[..E'N 
7-.!11%994J/0
 02
+,(lr   c                     |j                   |j                  |j                  |j                  xs dd|r|d   ndd}|j                  D ]  \  }}d|j                  dd      z   }|||<   ! |S )z.Build minimal environ dict for access logging.r  zHTTP/2r   r  r  r  rR  )r   r  r  r  rg   r  r  s           r   r  z!ASGIProtocol._build_http2_environ  ss     &nn{{ #MM/R'*28A;
 #??KD%DLLc22C GCL + r   )F)0r   r   r   r   r   r   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r  r  r  r  r  r  rI   rK   r$  r   r+  r-  r.  r/  rn  rr  rF  rY  r\  r]  r   r  r   r   r  r  r   r  r   r   r   r   r     s	    NO#' $LM< " "('#
8
t7",
/
)"V* )$V 
/
0
&Q$f-'^Q* "L8\+Z$$L5800d':%.N  E$N	vEp)Vr   r   )&r   r:   r  r&   rP   gunicorn.asgi.unreaderr   gunicorn.asgi.parserr   r   r   r   r   r	   gunicorn.asgi.uwsgir
   gunicorn.http.errorsr   gunicorn.uwsgi.errorsr   r   r"   r.   r\   r  rT   rQ   rangerS   r  r   r3   rV   rb   rd   rn   Protocolr   )is   0r   <module>r     s   
     0  2 + 5F F5(  4     ?DElKl11Tl)))44lK  %* %*P	%/ / m  m `s7## sG Ls   B9