
    AҐi!                     H    d dl Z d dlmZmZ d dlmZmZmZ dZ G d d      Z	y)    N)LengthReaderBody)InvalidUWSGIHeaderUnsupportedModifierForbiddenUWSGIRequesti  c                   H    e 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)UWSGIRequesta  uWSGI protocol request parser.

    The uWSGI protocol uses a 4-byte binary header:
    - Byte 0: modifier1 (packet type, 0 = WSGI request)
    - Bytes 1-2: datasize (16-bit little-endian, size of vars block)
    - Byte 3: modifier2 (additional flags, typically 0)

    After the header:
    1. Vars block (datasize bytes): Key-value pairs containing WSGI environ
       - Each pair: 2-byte key_size (LE) + key + 2-byte val_size (LE) + value
    2. Request body (determined by CONTENT_LENGTH in vars)
    c                    || _         || _        || _        || _        || _        d | _        d | _        d | _        d | _        d| _	        d| _
        g | _        g | _        d | _        |j                  rdnd| _        d| _        i | _        d| _        d| _        d | _        d| _        | j-                          | j/                  | j                        }| j                  j1                  |       | j3                          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_expected_100_continue_check_allowed_ipparseunreadset_body_reader)selfr   r   r   r   unuseds         O/var/www/descvideos/venv/lib/python3.12/site-packages/gunicorn/uwsgi/message.py__init__zUWSGIRequest.__init__!   s     "$$ 	
	!$g  $(  ',# 	  DMM*V$    c                     t        | j                  dddg      }t        | j                  t              syd|v ry| j                  d   |vrt        | j                  d         y)z(Verify source IP is in the allowed list.uwsgi_allow_ipsz	127.0.0.1z::1N*r   )getattrr   
isinstancer   tupler   )r)   	allow_ipss     r+   r%   zUWSGIRequest._check_allowed_ipH   sd    DHH&7+u9MN	 $..%0 )>>!I-'q(9:: .r-   c                     d| _         y)z1Force the connection to close after this request.TN)r   )r)   s    r+   force_closezUWSGIRequest.force_closeW   s	    r-   c                    | j                  |d      }t        |      dk  rt        d      |d   | _        t        j                  |dd d      }|d   | _        | j                  dk7  rt        | j                        |dkD  r<| j                  ||      }t        |      |k  rt        d      | j                  |       | j                          y)	z)Parse uWSGI packet header and vars block.   zincomplete headerr   r      littlezincomplete vars blockr-   )
_read_exactlenr   r!   int
from_bytesr"   r   _parse_vars_extract_request_info)r)   r   headerdatasize	vars_datas        r+   r&   zUWSGIRequest.parse[   s     !!(A.v;?$%899>>&1+x8 >>Q%dnn55 a<((8<I9~(()@AAY' 	""$r-   c                 $   t        j                         }|}|dkD  r=|j                         }|sn*|j                  |       ||j	                         z
  }|dkD  r=|j                         }t        |      |kD  r|j                  ||d        |d| }|S )z*Read exactly size bytes from the unreader.r   N)ioBytesIOreadwritetellgetvaluer<   r'   )r)   r   sizebuf	remainingdataresults          r+   r;   zUWSGIRequest._read_exactv   s    jjl	!m==?DIIdOsxxz)I !m v;OOF45M*ET]Fr-   c                 p   d}d}|t        |      k  r#|t        k\  rt        d      |dz   t        |      kD  rt        d      t        j	                  |||dz    d      }|dz  }||z   t        |      kD  rt        d      ||||z    j                  d      }||z  }|dz   t        |      kD  rt        d      t        j	                  |||dz    d      }|dz  }||z   t        |      kD  rt        d	      ||||z    j                  d      }||z  }|| j                  |<   |d
z  }|t        |      k  r"yy)zParse uWSGI vars block into key-value pairs.

        Format: key_size (2 bytes LE) + key + val_size (2 bytes LE) + value
        r   ztoo many variables   ztruncated key sizer:   ztruncated keyzlatin-1ztruncated value sizeztruncated valuer   N)r<   MAX_UWSGI_VARSr   r=   r>   decoder    )r)   rN   pos	var_countkey_sizekeyval_sizevalues           r+   r?   zUWSGIRequest._parse_vars   sX   
 	CIoN*()=>> QwT"()=>>~~d3sQw&7BH1HC X~D	)(99s3>*11)<C8OC QwT"()?@@~~d3sQw&7BH1HC X~D	)():;;S8^,33I>E8OC#(DOOC NI; CIor-   c                 J   | j                   j                  dd      | _        | j                   j                  dd      | _        | j                   j                  dd      | _        | j                  r!| j                  d| j                  | _        n| j                  | _        | j                   j                  dd      j                         d	v rd
| _        n"d| j                   v r| j                   d   | _        | j                   j                         D ]  \  }}|j                  d      r3|dd j                  dd      }| j                  j                  ||f       J|dk(  r| j                  j                  d|f       m|dk(  ss| j                  j                  d|f        y)a  Extract HTTP request info from uWSGI vars.

        Header Mapping (CGI/WSGI to HTTP):

        The uWSGI protocol passes HTTP headers using CGI-style environment
        variable naming. This method converts them back to HTTP header format:

        - HTTP_* vars: Strip 'HTTP_' prefix, replace '_' with '-'
          Example: HTTP_X_FORWARDED_FOR -> X-FORWARDED-FOR
          Example: HTTP_ACCEPT_ENCODING -> ACCEPT-ENCODING

        - CONTENT_TYPE: Mapped directly to CONTENT-TYPE header
          (CGI spec excludes HTTP_ prefix for this header)

        - CONTENT_LENGTH: Mapped directly to CONTENT-LENGTH header
          (CGI spec excludes HTTP_ prefix for this header)

        Note: The underscore-to-hyphen conversion is lossy. Headers that
        originally contained underscores (e.g., X_Custom_Header) cannot be
        distinguished from hyphenated headers (X-Custom-Header) after
        passing through nginx/uWSGI. This is a CGI/WSGI specification
        limitation, not specific to this implementation.
        REQUEST_METHODGET	PATH_INFO/QUERY_STRINGr   ?HTTPS)on1truer   zwsgi.url_schemeHTTP_   N_-CONTENT_TYPEzCONTENT-TYPECONTENT_LENGTHzCONTENT-LENGTH)r    getr   r   r   r   lowerr   items
startswithreplacer   append)r)   rW   rY   header_names       r+   r@   z"UWSGIRequest._extract_request_info   s[   2 oo))*:EB OO''S9	__((<
 ::"&))TZZ8DHyyDH ??w+1137JJ!DK$//1//*;<DK ////1 	?JC~~g&!!"gooc37##[%$89&##^U$;<((##%5u$=>	?r-   c                     d}d| j                   v r#	 t        t        | j                   d         d      }t	        t        | j                  |            | _        y# t        $ r d}Y 2w xY w)z/Set up the body reader based on CONTENT_LENGTH.r   rj   N)r    maxr=   
ValueErrorr   r   r   r   )r)   content_lengths     r+   r(   zUWSGIRequest.set_body_reader   sd     t.#!$S9I)J%KQ!O dmm^DE	  #!"#s   "A A'&A'c                     | j                   ry| j                  j                  dd      j                         }|dk(  ry|dk(  ryy)z@Determine if the connection should be closed after this request.THTTP_CONNECTIONr   closez
keep-aliveF)r   r    rk   rl   )r)   
connections     r+   should_closezUWSGIRequest.should_close   sI    ?? __(():B?EEG
 <' r-   N)r   )__name__
__module____qualname____doc__r,   r%   r6   r&   r;   r?   r@   r(   rz    r-   r+   r	   r	      s8    %N;6(%N5?nFr-   r	   )
rE   gunicorn.http.bodyr   r   gunicorn.uwsgi.errorsr   r   r   rR   r	   r   r-   r+   <module>r      s*   
 
 1  o or-   