
    AҐi                     :    d Z ddlmZ ddlmZmZ  G d de      Zy)zAsync uWSGI protocol parser for ASGI workers.

Reuses the parsing logic from gunicorn/uwsgi/message.py, only async I/O differs.
    )UWSGIRequest)InvalidUWSGIHeaderUnsupportedModifierc                   P    e Zd ZdZddZedd       Zd Zd Zd Z	ddZ
d Zd	 Zy
)AsyncUWSGIRequestaR  Async version of UWSGIRequest.

    Reuses all parsing logic from the sync version, only async I/O differs.
    The following methods are reused from the parent class:
    - _parse_vars() - pure parsing, no I/O
    - _extract_request_info() - pure transformation
    - _check_allowed_ip() - no I/O
    - should_close() - simple logic
    c                 b   || _         || _        || _        || _        || _        d | _        d | _        d | _        d | _        d| _	        d| _
        g | _        g | _        d | _        |j                  rdnd| _        d| _        i | _        d| _        d| _        d | _        d| _        d| _        d| _        y )N )   r
   httpshttpFr   )cfgunreader	peer_addrremote_addr
req_numbermethoduripathqueryfragmentversionheaderstrailersbodyis_sslscheme
must_close
uwsgi_vars	modifier1	modifier2proxy_protocol_infocontent_lengthchunked_body_remaining)selfr   r   r   r   s        L/var/www/descvideos/venv/lib/python3.12/site-packages/gunicorn/asgi/uwsgi.py__init__zAsyncUWSGIRequest.__init__   s      "$$ 	
	!$g#'        c                 x   K    | ||||      }|j                          |j                          d{    |S 7 w)a  Parse a uWSGI request asynchronously.

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

        Returns:
            AsyncUWSGIRequest: Parsed request object

        Raises:
            InvalidUWSGIHeader: If the uWSGI header is malformed
            UnsupportedModifier: If modifier1 is not 0
            ForbiddenUWSGIRequest: If source IP is not allowed
        N)_check_allowed_ip_async_parse)clsr   r   r   r   reqs         r&   parsezAsyncUWSGIRequest.parse@   s@     $ #xJ7   
 	!s   /:8:c                   K   | j                  d       d{   }t        |      dk  rt        d      |d   | _        t        j                  |dd d      }|d   | _        | j                  dk7  rt        | j                        |dkD  rC| j                  |       d{   }t        |      |k  rt        d      | j                  |       | j                          | j                          y7 7 Qw)	z=Async version of parse() - reads data then uses sync parsing.   Nzincomplete headerr   r
      littlezincomplete vars block)_async_read_exactlenr   r   int
from_bytesr    r   _parse_vars_extract_request_info_set_body_reader)r%   headerdatasize	vars_datas       r&   r+   zAsyncUWSGIRequest._async_parseW   s      --a00v;?$%899>>&1+x8>>Q%dnn55 a<"44X>>I9~(()@AAY'""$' 1 ?s#   C3C/BC3C1 AC31C3c                   K   t               }t        |      |k  r]| j                  j                  |t        |      z
         d{   }|s	 t        |      S |j	                  |       t        |      |k  r]t        |      S 7 =w)z'Read exactly size bytes asynchronously.N)	bytearrayr4   r   readextendbytes)r%   sizebufchunks       r&   r3   z#AsyncUWSGIRequest._async_read_exacto   ss     k#ho--,,TCH_==ESz JJu	 #ho
 Sz	 >s   ABB1B8Bc                     d}d| j                   v r#	 t        t        | j                   d         d      }|| _        || _        y# t        $ r d}Y w xY w)z$Set up body state for async reading.r   CONTENT_LENGTHN)r   maxr5   
ValueErrorr"   r$   )r%   r"   s     r&   r9   z"AsyncUWSGIRequest._set_body_readery   s[    t.#!$S9I)J%KQ!O --  #!"#s   "A AAc                    K   | j                   dk  ryt        || j                         }| j                  j                  |       d{   }|r| xj                   t	        |      z  c_         |S 7 &w)zRead body chunk asynchronously.

        Args:
            size: Maximum bytes to read

        Returns:
            bytes: Body data, empty bytes when body is exhausted
        r   r(   N)r$   minr   r?   r4   )r%   rB   to_readdatas       r&   	read_bodyzAsyncUWSGIRequest.read_body   sd      1$dD001]]''00  CI-  1s   AA0A.'A0c                    K   | j                   dkD  r-| j                  d       d{   }|sy| j                   dkD  r,yy7 w)zcDrain unread body data.

        Should be called before reusing connection for keepalive.
        r       N)r$   rM   )r%   rL   s     r&   
drain_bodyzAsyncUWSGIRequest.drain_body   s@     
 ""Q&--D ""Q&-s   $AA AAc                 ^    |j                         }| j                  D ]  \  }}||k(  s|c S  y)zGet header by name (case-insensitive).

        Args:
            name: Header name to look up

        Returns:
            Header value if found, None otherwise
        N)upperr   )r%   namehvs       r&   
get_headerzAsyncUWSGIRequest.get_header   s7     zz|LL 	DAqDy	 r(   N)r
   )rO   )__name__
__module____qualname____doc__r'   classmethodr.   r+   r3   r9   rM   rP   rV    r(   r&   r   r      s?    !F  , 0	."r(   r   N)rZ   gunicorn.uwsgi.messager   gunicorn.uwsgi.errorsr   r   r   r\   r(   r&   <module>r_      s"   

 0[ [r(   