
    g;                        d Z ddl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 ddlZddlZddlmZ ddlZddlZddlmZmZmZmZ ddlmZmZmZ ddlmZ dd	lmZm Z  e ddl!Z!dd
l!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, e!jZ                  rddl!m.Z. ddl/m0Z0 ddl1Z1dZ2 e	d      de3de3fd       Z4 G d dejj                  jl                        Z7 G d de8      Z9 G d de:      Z; G d de:      Z< G d de8      Z= G d de8      Z> G d de8      Z?d e3d!e(de'e3e3f   e$e"e3e3f      e"e"e3e3f   d"f   f   de3fd#Z@ G d$ d%e      ZAd&e3de)e"e)eB   e)eB   f      fd'ZCd(e)eB   d)e)eB   d*eBde3fd+ZDd,e3de)eB   fd-ZE	 dWd.e3d/eFd0e'e3e$eF   f   d1e'e3e$eA   f   d2e)e7   ddfd3ZGd4eFd5eFd0e'e3e$eF   f   d1e'e3e$eA   f   ddf
d6ZHd7e(eBeIeJej                  ej
                  f   de3fd8ZL ej                  d9g d:      ZN ej                  d;      ZPd<e3deNfd=ZQ ej                  d>g d?      ZR ej                  d@      ZSd<e3deRfdAZTdBe3de+e3ddf   fdCZUd<e3de"e3e'e3e3f   f   fdDZVdEe3dFe'e3e3f   de3fdGZWdHe(e3eFf   dIe(e3eFf   deFfdJZXdK ZY ej                  dL      ZZdMe3de"e3e)eB   f   fdNZ[dOe'e3e$e,   f   de#e"e3e,f      fdPZ\ ej                  dQ      j                  Z^dRej                  de3fdSZ`dBe3de3fdTZadUe3de'e3e3f   fdVZby)XzHTTP utility code shared by clients and servers.

This module also defines the `HTTPServerRequest` class which is exposed
via `tornado.web.RequestHandler.request`.
    N)	lru_cache)	responses)SSLError)	urlencodeurlparse
urlunparse	parse_qsl)
native_strparse_qs_bytesutf8)gen_log)
ObjectDictunicode_type)TupleIterableListMappingIteratorDictUnionOptional	Awaitable	GeneratorAnyStr)Deque)Futurez 	i  namereturnc                     dj                  | j                  d      D cg c]  }|j                          c}      S c c}w )ziMap a header name to Http-Header-Case.

    >>> _normalize_header("coNtent-TYPE")
    'Content-Type'
    -)joinsplit
capitalize)r   ws     E/var/www/openai/venv/lib/python3.12/site-packages/tornado/httputil.py_normalize_headerr&   E   s3     88TZZ_=_Q\\^_=>>=s   =c                      e Zd ZdZej
                  deeee   f   ddfd       Z	ej
                  deeef   ddfd       Z	ej
                  de
eef   ddfd       Z	ej
                  d	eddfd
       Z	dej                  d	eddfdZ	dededdfdZdedee   fdZdee
eef      fdZdeddfdZededd fd       ZdededdfdZdedefdZdeddfdZdefdZdeej                     fdZddZeZdefdZeZy)HTTPHeadersa  A dictionary that maintains ``Http-Header-Case`` for all keys.

    Supports multiple values per key via a pair of new methods,
    `add()` and `get_list()`.  The regular dictionary interface
    returns a single value per key, with multiple values joined by a
    comma.

    >>> h = HTTPHeaders({"content-type": "text/html"})
    >>> list(h.keys())
    ['Content-Type']
    >>> h["Content-Type"]
    'text/html'

    >>> h.add("Set-Cookie", "A=B")
    >>> h.add("Set-Cookie", "C=D")
    >>> h["set-cookie"]
    'A=B,C=D'
    >>> h.get_list("set-cookie")
    ['A=B', 'C=D']

    >>> for (k,v) in sorted(h.get_all()):
    ...    print('%s: %s' % (k,v))
    ...
    Content-Type: text/html
    Set-Cookie: A=B
    Set-Cookie: C=D
    _HTTPHeaders__argr   Nc                      y N selfr)   s     r%   __init__zHTTPHeaders.__init__l           c                      y r+   r,   r-   s     r%   r/   zHTTPHeaders.__init__p   r0   r1   argsc                      y r+   r,   )r.   r3   s     r%   r/   zHTTPHeaders.__init__t   r0   r1   kwargsc                      y r+   r,   )r.   r5   s     r%   r/   zHTTPHeaders.__init__x   r0   r1   c                    i | _         i | _        d | _        t        |      dk(  rOt        |      dk(  rAt	        |d   t
              r.|d   j                         D ]  \  }}| j                  ||        y  | j                  |i | y )N   r   )	_dict_as_list	_last_keylen
isinstancer(   get_alladdupdate)r.   r3   r5   kvs        r%   r/   zHTTPHeaders.__init__|   su    
t9>c&kQ.:d1g{3SQ)1A * DKK((r1   r   valuec                     t        |      }|| _        || v rIt        | |         dz   t        |      z   | j                  |<   | j                  |   j                  |       y|| |<   y)z#Adds a new value for the given key.,N)r&   r;   r
   r9   r:   appendr.   r   rC   	norm_names       r%   r?   zHTTPHeaders.add   sf    %d+	"4	?+c1Ju4EE JJy! MM)$++E2#DOr1   c                 P    t        |      }| j                  j                  |g       S )z2Returns all values for the given header as a list.)r&   r:   getr.   r   rH   s      r%   get_listzHTTPHeaders.get_list   s#    %d+	}}  B//r1   c              #   j   K   | j                   j                         D ]  \  }}|D ]  }||f 
  yw)zReturns an iterable of all (name, value) pairs.

        If a header has multiple values, multiple pairs will be
        returned with the same name.
        N)r:   items)r.   r   valuesrC   s       r%   r>   zHTTPHeaders.get_all   s7      !MM//1LD&Um#   2s   13linec                    |d   j                         ru| j                  t        d      d|j                  t              z   }| j
                  | j                     dxx   |z  cc<   | j                  | j                  xx   |z  cc<   y	 |j                  dd      \  }}| j                  ||j                  t                     y# t        $ r t        d      w xY w)	zUpdates the dictionary with a single header line.

        >>> h = HTTPHeaders()
        >>> h.parse_line("Content-Type: text/html")
        >>> h.get('content-type')
        'text/html'
        r   Nz.first header line cannot start with whitespace :r8   zno colon in header line)isspacer;   HTTPInputErrorlstripHTTP_WHITESPACEr:   r9   r"   
ValueErrorr?   strip)r.   rP   new_partr   rC   s        r%   
parse_linezHTTPHeaders.parse_line   s     7??~~%$%UVVT[[99HMM$..)"-9-JJt~~&(2&@"jja0e HHT5;;78  @$%>??@s   
C Cheadersc                      |        }|j                  d      D ],  }|j                  d      r|dd }|s|j                  |       . |S )a  Returns a dictionary from HTTP header text.

        >>> h = HTTPHeaders.parse("Content-Type: text/html\r\nContent-Length: 42\r\n")
        >>> sorted(h.items())
        [('Content-Length', '42'), ('Content-Type', 'text/html')]

        .. versionchanged:: 5.1

           Raises `HTTPInputError` on malformed headers instead of a
           mix of `KeyError`, and `ValueError`.

        
NrS   )r"   endswithr\   )clsr]   hrP   s       r%   parsezHTTPHeaders.parse   sM     E MM$'D}}T"CRyT"	 (
 r1   c                 X    t        |      }|| j                  |<   |g| j                  |<   y r+   r&   r9   r:   rG   s       r%   __setitem__zHTTPHeaders.__setitem__   s*    %d+	 %

9$)7i r1   c                 2    | j                   t        |         S r+   )r9   r&   )r.   r   s     r%   __getitem__zHTTPHeaders.__getitem__   s    zz+D122r1   c                 N    t        |      }| j                  |= | j                  |= y r+   rf   rK   s      r%   __delitem__zHTTPHeaders.__delitem__   s$    %d+	JJy!MM)$r1   c                 ,    t        | j                        S r+   )r<   r9   r.   s    r%   __len__zHTTPHeaders.__len__   s    4::r1   c                 ,    t        | j                        S r+   )iterr9   rm   s    r%   __iter__zHTTPHeaders.__iter__   s    DJJr1   c                     t        |       S r+   )r(   rm   s    r%   copyzHTTPHeaders.copy   s    4  r1   c                     g }| j                         D ]  \  }}|j                  |d|d        dj                  |      S )Nz: r_    )r>   rF   r!   )r.   linesr   rC   s       r%   __str__zHTTPHeaders.__str__   s:    <<>KD%LLtU34 *wwu~r1   )r   r(   )__name__
__module____qualname____doc__typingoverloadr   strr   r/   r   Anyr?   rL   r   r>   r\   classmethodrd   rg   ri   rk   intrn   r   rq   rs   __copy__rw   __unicode__r,   r1   r%   r(   r(   O   s   8 __gc49n5 $   __gc3h/ D   __eCHo $   __   
)fjj 
)C 
)D 
)
$ 
$C 
$D 
$0S 0T#Y 0
$%S/2 $9s 9t 9, C M  2+ +C +D +
3 3 3% % %
  (6::.  ! H  Kr1   r(   c                   @   e Zd ZdZdZdZdZ	 	 	 	 	 	 	 	 	 	 ddee   dee   dedee	   dee
   dee   d	eeeed
   f      ded   ded   dee   ddfdZedeeej"                  j$                  f   fd       ZdefdZdefdZ	 ddededee
f   fdZddZdefdZy)HTTPServerRequesta7
  A single HTTP request.

    All attributes are type `str` unless otherwise noted.

    .. attribute:: method

       HTTP request method, e.g. "GET" or "POST"

    .. attribute:: uri

       The requested uri.

    .. attribute:: path

       The path portion of `uri`

    .. attribute:: query

       The query portion of `uri`

    .. attribute:: version

       HTTP version specified in request, e.g. "HTTP/1.1"

    .. attribute:: headers

       `.HTTPHeaders` dictionary-like object for request headers.  Acts like
       a case-insensitive dictionary with additional methods for repeated
       headers.

    .. attribute:: body

       Request body, if present, as a byte string.

    .. attribute:: remote_ip

       Client's IP address as a string.  If ``HTTPServer.xheaders`` is set,
       will pass along the real IP address provided by a load balancer
       in the ``X-Real-Ip`` or ``X-Forwarded-For`` header.

    .. versionchanged:: 3.1
       The list format of ``X-Forwarded-For`` is now supported.

    .. attribute:: protocol

       The protocol used, either "http" or "https".  If ``HTTPServer.xheaders``
       is set, will pass along the protocol used by a load balancer if
       reported via an ``X-Scheme`` header.

    .. attribute:: host

       The requested hostname, usually taken from the ``Host`` header.

    .. attribute:: arguments

       GET/POST arguments are available in the arguments property, which
       maps arguments names to lists of values (to support multiple values
       for individual names). Names are of type `str`, while arguments
       are byte strings.  Note that this is different from
       `.RequestHandler.get_argument`, which returns argument values as
       unicode strings.

    .. attribute:: query_arguments

       Same format as ``arguments``, but contains only arguments extracted
       from the query string.

       .. versionadded:: 3.2

    .. attribute:: body_arguments

       Same format as ``arguments``, but contains only arguments extracted
       from the request body.

       .. versionadded:: 3.2

    .. attribute:: files

       File uploads are available in the files property, which maps file
       names to lists of `.HTTPFile`.

    .. attribute:: connection

       An HTTP request is attached to a single HTTP connection, which can
       be accessed through the "connection" attribute. Since connections
       are typically kept open in HTTP/1.1, multiple requests can be handled
       sequentially on a single connection.

    .. versionchanged:: 4.0
       Moved from ``tornado.httpserver.HTTPRequest``.
    Nmethoduriversionr]   bodyhostfilesHTTPFile
connectionHTTPConnection
start_lineRequestStartLineserver_connectionr   c                    |	|	\  }}}|| _         || _        || _        |xs
 t               | _        |xs d| _        t        |dd       }t        |dd       | _        t        |dd      | _        |xs | j                  j                  d      xs d| _
        t        | j                  j                               d   | _        |xs i | _        || _        |
| _        t#        j"                         | _        d | _        ||j)                  d	      \  | _        }| _        t/        | j,                  d
      | _        t3        j4                  | j0                        | _        i | _        y )Nr1   context	remote_ipprotocolhttpHostz	127.0.0.1r   ?Tkeep_blank_values)r   r   r   r(   r]   r   getattrr   r   rJ   r   split_host_and_portlower	host_namer   r   r   time_start_time_finish_time	partitionpathqueryr   	argumentsrs   deepcopyquery_argumentsbody_arguments)r.   r   r   r   r]   r   r   r   r   r   r   r   seps                r%   r/   zHTTPServerRequest.__init__]  s-    !#- FC/+-KC	 *i6 +t<V<CDLL,,V4C	,TYY__->?B[b
$!299; ?),s);&DIsDJ'

dK#}}T^^< r1   c                    t        | d      s~t        j                  j                         | _        d| j
                  v rM	 t        | j
                  d         }|j                         D ]  \  }}	 || j                  |<    | j                  S | j                  S # t        $ r Y ;w xY w# t        $ r Y | j                  S w xY w)z0A dictionary of ``http.cookies.Morsel`` objects._cookiesCookie)	hasattrr   cookiesSimpleCookier   r]   parse_cookierN   	Exception)r.   parsedrA   rB   s       r%   r   zHTTPServerRequest.cookies  s     tZ())+ M 4<<'!)$,,x*@AF !'1!/0DMM!, !/ }}t}}  ) ! !	! !  }}s#   B& .B	B#"B#&	B=<B=c                 T    | j                   dz   | j                  z   | j                  z   S )z+Reconstructs the full URL for this request.z://)r   r   r   rm   s    r%   full_urlzHTTPServerRequest.full_url  s#    }}u$tyy0488;;r1   c                     | j                   !t        j                         | j                  z
  S | j                   | j                  z
  S )z?Returns the amount of time it took for this request to execute.)r   r   r   rm   s    r%   request_timezHTTPServerRequest.request_time  s<    $99;!1!111$$t'7'777r1   binary_formc                     	 | j                   y| j                   j                  j                  j                  |      S # t        $ r Y yw xY w)a>  Returns the client's SSL certificate, if any.

        To use client certificates, the HTTPServer's
        `ssl.SSLContext.verify_mode` field must be set, e.g.::

            ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            ssl_ctx.load_cert_chain("foo.crt", "foo.key")
            ssl_ctx.load_verify_locations("cacerts.pem")
            ssl_ctx.verify_mode = ssl.CERT_REQUIRED
            server = HTTPServer(app, ssl_options=ssl_ctx)

        By default, the return value is a dictionary (or None, if no
        client certificate is present).  If ``binary_form`` is true, a
        DER-encoded form of the certificate is returned instead.  See
        SSLSocket.getpeercert() in the standard library for more
        details.
        http://docs.python.org/library/ssl.html#sslsocket-objects
        N)r   )r   streamsocketgetpeercertr   )r.   r   s     r%   get_ssl_certificatez%HTTPServerRequest.get_ssl_certificate  sS    *	&??))00<<' =    		s   ? /? 	A
Ac                 @   t        | j                  j                  dd      | j                  | j                  | j
                  | j                         | j                  j                         D ]0  \  }}| j                  j                  |g       j                  |       2 y )NContent-Typeru   )
parse_body_argumentsr]   rJ   r   r   r   rN   r   
setdefaultextend)r.   rA   rB   s      r%   _parse_bodyzHTTPServerRequest._parse_body  sz    LL^R0IIJJLL	
 ''--/DAqNN%%a,33A6 0r1   c                     d}dj                  |D cg c]  }|dt        | |       c}      }| j                  j                  d|dS c c}w )N)r   r   r   r   r   r   z, =())r!   r   	__class__rx   )r.   attrsnr3   s       r%   __repr__zHTTPServerRequest.__repr__  sK    Myy5I5aQa(895IJ>>22D99 Js   A)
NNzHTTP/1.0NNNNNNN)Fr   N)rx   ry   rz   r{   r   r   _body_futurer   r~   r(   bytesr   r   objectr/   propertyr   r   Morselr   floatr   boolr   r   r   r   r,   r1   r%   r   r      sf   Zx DE L !%!!)- $"7;1537.2&!&! c]&! 	&!
 +&&! uo&! sm&! S$z"2234&! -.&! /0&! $F+&! 
&!P c4<<#6#667  ,<# <8e 8 #(	tT5 	!>
7:# :r1   r   c                       e Zd ZdZy)rV   zqException class for malformed HTTP requests or responses
    from remote sources.

    .. versionadded:: 4.0
    Nrx   ry   rz   r{   r,   r1   r%   rV   rV     s     	r1   rV   c                       e Zd ZdZy)HTTPOutputErrorzJException class for errors in HTTP output.

    .. versionadded:: 4.0
    Nr   r,   r1   r%   r   r     s    
 	r1   r   c                   4    e Zd ZdZdeddddfdZdeddfd	Zy)
HTTPServerConnectionDelegatez_Implement this interface to handle requests from `.HTTPServer`.

    .. versionadded:: 4.0
    server_connrequest_connr   r   HTTPMessageDelegatec                     t               )aj  This method is called by the server when a new request has started.

        :arg server_conn: is an opaque object representing the long-lived
            (e.g. tcp-level) connection.
        :arg request_conn: is a `.HTTPConnection` object for a single
            request/response exchange.

        This method should return a `.HTTPMessageDelegate`.
        NotImplementedError)r.   r   r   s      r%   start_requestz*HTTPServerConnectionDelegate.start_request  s     "##r1   Nc                      y)zThis method is called when a connection has been closed.

        :arg server_conn: is a server connection that has previously been
            passed to ``start_request``.
        Nr,   )r.   r   s     r%   on_closez%HTTPServerConnectionDelegate.on_close       	r1   )rx   ry   rz   r{   r   r   r   r,   r1   r%   r   r     s7    
$!$1A$	$F t r1   r   c                   b    e Zd ZdZded   dedeed      fdZde	deed      fd	Z
dd
ZddZy)r   z_Implement this interface to handle an HTTP request or response.

    .. versionadded:: 4.0
    r   r   ResponseStartLiner]   r   Nc                      y)a  Called when the HTTP headers have been received and parsed.

        :arg start_line: a `.RequestStartLine` or `.ResponseStartLine`
            depending on whether this is a client or server message.
        :arg headers: a `.HTTPHeaders` instance.

        Some `.HTTPConnection` methods can only be called during
        ``headers_received``.

        May return a `.Future`; if it does the body will not be read
        until it is done.
        Nr,   )r.   r   r]   s      r%   headers_receivedz$HTTPMessageDelegate.headers_received  s    " 	r1   chunkc                      y)ziCalled when a chunk of data has been received.

        May return a `.Future` for flow control.
        Nr,   r.   r   s     r%   data_receivedz!HTTPMessageDelegate.data_received"  s    
 	r1   c                      y)z6Called after the last chunk of data has been received.Nr,   rm   s    r%   finishzHTTPMessageDelegate.finish)  r0   r1   c                      y)zCalled if the connection is closed without finishing the request.

        If ``headers_received`` is called, either ``finish`` or
        ``on_connection_close`` will be called, but not both.
        Nr,   rm   s    r%   on_connection_closez'HTTPMessageDelegate.on_connection_close-  r   r1   r   )rx   ry   rz   r{   r   r(   r   r   r   r   r   r   r   r,   r1   r%   r   r     s]    AB  
)D/	"	&5 Xio-F r1   r   c            	       P    e Zd ZdZ	 dded   dedee   ddfd	Zdeddfd
Z	ddZ
y)r   zYApplications use this interface to write their responses.

    .. versionadded:: 4.0
    Nr   r   r]   r   r   zFuture[None]c                     t               )a  Write an HTTP header block.

        :arg start_line: a `.RequestStartLine` or `.ResponseStartLine`.
        :arg headers: a `.HTTPHeaders` instance.
        :arg chunk: the first (optional) chunk of data.  This is an optimization
            so that small responses can be written in the same call as their
            headers.

        The ``version`` field of ``start_line`` is ignored.

        Returns a future for flow control.

        .. versionchanged:: 6.0

           The ``callback`` argument was removed.
        r   )r.   r   r]   r   s       r%   write_headerszHTTPConnection.write_headers<  s    , "##r1   c                     t               )zWrites a chunk of body data.

        Returns a future for flow control.

        .. versionchanged:: 6.0

           The ``callback`` argument was removed.
        r   r   s     r%   writezHTTPConnection.writeT  s     "##r1   c                     t               )z3Indicates that the last body data has been written.r   rm   s    r%   r   zHTTPConnection.finish_  s    !##r1   r+   r   )rx   ry   rz   r{   r   r(   r   r   r   r   r   r,   r1   r%   r   r   6  sY     "&	$AB$ $ 	$
 
$0	$5 	$^ 	$$r1   r   urlr3   .c           	         || S t        |       }t        |t              r7t        |j                  d      }|j                  |j                                nnt        |t              st        |t              r)t        |j                  d      }|j                  |       n%dj                  t        |            }t        |      t        |      }t        |d   |d   |d   |d   ||d   f      } | S )	a  Concatenate url and arguments regardless of whether
    url has existing query parameters.

    ``args`` may be either a dictionary or a list of key-value pairs
    (the latter allows for multiple values with the same key.

    >>> url_concat("http://example.com/foo", dict(c="d"))
    'http://example.com/foo?c=d'
    >>> url_concat("http://example.com/foo?a=b", dict(c="d"))
    'http://example.com/foo?a=b&c=d'
    >>> url_concat("http://example.com/foo?a=b", [("c", "d"), ("c", "d2")])
    'http://example.com/foo?a=b&c=d&c=d2'
    Tr   z7'args' parameter should be dict, list or tuple. Not {0}r   r8            )r   r=   dictr	   r   r   rN   listtupleformattype	TypeErrorr   r   )r   r3   
parsed_urlparsed_queryerrfinal_querys         r%   
url_concatr  d  s    & |
#J$ !1!1TJDJJL)	D$	:dE#: !1!1TJD!GNNJ
 nL)K
qMqMqMqMqM	
	C Jr1   c                   0    e Zd ZU dZeed<   eed<   eed<   y)r   zRepresents a file uploaded via a form.

    For backwards compatibility, its instance attributes are also
    accessible as dictionary keys.

    * ``filename``
    * ``body``
    * ``content_type``
    filenamer   content_typeN)rx   ry   rz   r{   r~   __annotations__r   r,   r1   r%   r   r     s     M
Kr1   r   range_headerc                 $   | j                  d      \  }}}|j                         |j                         }}|dk7  ry|j                  d      \  }}}	 t        |      }t        |      }|||dk7  r| }d}||fS |dz  }||fS # t        $ r Y yw xY w)ag  Parses a Range header.

    Returns either ``None`` or tuple ``(start, end)``.
    Note that while the HTTP headers use inclusive byte positions,
    this method returns indexes suitable for use in slices.

    >>> start, end = _parse_request_range("bytes=1-2")
    >>> start, end
    (1, 3)
    >>> [0, 1, 2, 3, 4][start:end]
    [1, 2]
    >>> _parse_request_range("bytes=6-")
    (6, None)
    >>> _parse_request_range("bytes=-6")
    (-6, None)
    >>> _parse_request_range("bytes=-0")
    (None, 0)
    >>> _parse_request_range("bytes=")
    (None, None)
    >>> _parse_request_range("foo=42")
    >>> _parse_request_range("bytes=1-2,6-10")

    Note: only supports one range (ex, ``bytes=1-2,6-10`` is not allowed).

    See [0] for the details of the range header.

    [0]: http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p5-range-latest.html#byte.ranges
    r   r   Nr    r   r8   )r   rZ   _int_or_nonerY   )r
  unit_rC   start_bend_bstartends           r%   _parse_request_ranger    s    > "++C0ND!U**,%Dw,GQW%5! =ax 3< 1HC3<  s   B 	BBr  r  totalc                 6    | xs d} |xs |dz
  }d| d|d|S )zReturns a suitable Content-Range header:

    >>> print(_get_content_range(None, 1, 4))
    bytes 0-0/4
    >>> print(_get_content_range(1, 3, 4))
    bytes 1-2/4
    >>> print(_get_content_range(None, None, 4))
    bytes 0-3/4
    r   r8   zbytes r    /r,   )r  r  r  s      r%   _get_content_ranger    s(     JQE<%1
C$c511r1   valc                 D    | j                         } | dk(  ry t        |       S )Nru   )rZ   r   )r  s    r%   r  r    s     
))+C
bys8Or1   r  r   r   r   r]   c                    | j                  d      rk|rd|v rt        j                  d|d          y	 t        |d      }|j                         D ])  \  }}|s	|j                  |g       j                  |       + y| j                  d      r|rd|v rt        j                  d|d          y	 | j                  d	      }	|	D ]F  }
|
j                         j                  d
      \  }}}|dk(  s,|s/t        t        |      |||        y t        d      y# t        $ r"}t        j                  d|       i }Y d}~d}~ww xY w# t        $ r }t        j                  d|       Y d}~yd}~ww xY w)aF  Parses a form request body.

    Supports ``application/x-www-form-urlencoded`` and
    ``multipart/form-data``.  The ``content_type`` parameter should be
    a string and ``body`` should be a byte string.  The ``arguments``
    and ``files`` parameters are dictionaries that will be updated
    with the parsed contents.
    z!application/x-www-form-urlencodedzContent-Encodingz Unsupported Content-Encoding: %sNTr   z&Invalid x-www-form-urlencoded body: %szmultipart/form-data;r   boundaryzmultipart boundary not foundzInvalid multipart/form-data: %s)
startswithr   warningr   r   rN   r   r   r"   rZ   r   parse_multipart_form_datar   rY   )r  r   r   r   r]   uri_argumentser   rO   fieldsfieldrA   r   rB   s                 r%   r   r     sr    BC)W4OO2G<N4O 	*44HM *//1LD&$$T2.55f= 2 
	 	 !6	7)W4OO2G<N4O 
	B!'',F!KKM33C8	3
?q-d1gtYN	   !!?@@ 
8  	OODaHM	*  	BOO=qAA	BsA   D />E .E 1E 
E 	E D==E	E.E))E.r  datac                    | j                  d      r| j                  d      r| dd } |j                  d| z   dz         }|dk(  rt        j                  d       y|d| j                  d| z   dz         }|D ]O  }|s|j                  d      }|dk(  rt        j                  d	       3t        j                  |d| j                  d
            }|j                  dd      }	t        |	      \  }
}|
dk7  s|j                  d      st        j                  d       ||dz   d }|j                  d      st        j                  d       |d   }|j                  d      rD|j                  dd      }|j                  |g       j                  t        |d   ||             /|j                  |g       j                  |       R y)a]  Parses a ``multipart/form-data`` body.

    The ``boundary`` and ``data`` parameters are both byte strings.
    The dictionaries given in the arguments and files parameters
    will be updated with the contents of the body.

    .. versionchanged:: 5.1

       Now recognizes non-ASCII filenames in RFC 2231/5987
       (``filename*=``) format.
       "r8   rS   s   --z.Invalid multipart/form-data: no final boundaryNs   
s   

z#multipart/form-data missing headerszutf-8zContent-Dispositionru   z	form-datazInvalid multipart/form-data   r   z&multipart/form-data value missing namer  r   zapplication/unknown)r  r   r  )r  ra   rfindr   r  r"   findr(   rd   decoderJ   _parse_headerr   rF   r   )r  r$  r   r   final_boundary_indexpartsparteohr]   disp_headerdispositiondisp_paramsrC   r   ctypes                  r%   r  r    s   , 4 X%6%6t%<Ab>::eh&6&>?r!HI&&'--eh.>.HIEii$"9OOAB##D#J$5$5g$>?kk"7<#0#= [+%T]]7-COO9:S1Wr"v&OODE6"??:&KK0EFET2&--(45u   r*11%85 r1   tsc                 z   t        | t        t        f      r| }nt        | t        t        j
                  f      rt        j                  |       }nLt        | t        j                        r$t        j                  | j                               }nt        d| z        t        j                  j                  |d      S )a  Formats a timestamp in the format used by HTTP.

    The argument may be a numeric timestamp as returned by `time.time`,
    a time tuple as returned by `time.gmtime`, or a `datetime.datetime`
    object. Naive `datetime.datetime` objects are assumed to represent
    UTC; aware objects are converted to UTC before formatting.

    >>> format_timestamp(1359312200)
    'Sun, 27 Jan 2013 18:43:20 GMT'
    zunknown timestamp type: %rT)usegmt)r=   r   r   r   r   struct_timecalendartimegmdatetimeutctimetupler   emailutils
formatdate)r5  time_nums     r%   format_timestamprA  W  s     "sEl#	B 0 01	2??2&	B))	*??2??#454r9::;;!!(4!88r1   r   )r   r   r   z^HTTP/1\.[0-9]$rP   c                     	 | j                  d      \  }}}t        j	                  |      st        d|z        t        |||      S # t        $ r t        d      w xY w)zReturns a (method, path, version) tuple for an HTTP 1.x request line.

    The response is a `collections.namedtuple`.

    >>> parse_request_start_line("GET /foo HTTP/1.1")
    RequestStartLine(method='GET', path='/foo', version='HTTP/1.1')
    rR   zMalformed HTTP request linez/Malformed HTTP version in HTTP Request-Line: %r)r"   rY   rV   _http_version_rematchr   )rP   r   r   r   s       r%   parse_request_start_linerE  w  sp    < $

3g
 !!'*=G
 	
 FD'22  < :;;<s   A Ar   )r   codereasonz (HTTP/1.[0-9]) ([0-9]+) ([^\r]*)c                     t        |       } t        j                  |       }|st        d      t	        |j                  d      t        |j                  d            |j                  d            S )zReturns a (version, code, reason) tuple for an HTTP 1.x response line.

    The response is a `collections.namedtuple`.

    >>> parse_response_start_line("HTTP/1.1 200 OK")
    ResponseStartLine(version='HTTP/1.1', code=200, reason='OK')
    z!Error parsing response start liner8   r   r   )r
   _http_response_line_rerD  rV   r   groupr   )rP   rD  s     r%   parse_response_start_linerK    sY     dD"((.E@AAU[[^SQ-@%++a.QQr1   sc              #     K   | d d dk(  r| dd  } | j                  d      }|dkD  ro| j                  dd|      | j                  dd|      z
  dz  rE| j                  d|dz         }|dkD  r+| j                  dd|      | j                  dd|      z
  dz  rE|dk  rt        |       }| d | }|j                          | |d  } | d d dk(  ry y w)Nr8   r  r   "z\"r   )r*  countr<   rZ   )rL  r  fs      r%   _parseparamrQ    s     
BQ%3,abEffSkAg17733/!''%C2HHAM&&cAg&C Ag17733/!''%C2HHAM7a&CdsGggicdG BQ%3,s   BC4C
Cc                 *   t        d| z         }t        |      }dg}|D ]l  }|j                  d      }|dk\  s|d| j                         j	                         }||dz   d j                         }|j                  |t        |      f       n t        j                  j                  |      }|j                  d       i }	|D ]L  \  }}
t        j                  j                  |
      }t        |      dk\  r|d   dk(  r|d	   dk(  r|dd	 }||	|<   N ||	fS )
aY  Parse a Content-type like header.

    Return the main content-type and a dictionary of options.

    >>> d = "form-data; foo=\"b\\\\a\\\"r\"; file*=utf-8''T%C3%A4st"
    >>> ct, d = _parse_header(d)
    >>> ct
    'form-data'
    >>> d['file'] == r'T\u00e4st'.encode('ascii').decode('unicode_escape')
    True
    >>> d['foo']
    'b\\a"r'
    r  )DummyrC   r   r   Nr8   r   rN  rS   )rQ  nextr*  rZ   r   rF   r
   r=  r>  decode_paramspopcollapse_rfc2231_valuer<   )rP   r.  keyparamspir   rC   decoded_paramspdictdecoded_values              r%   r,  r,    s    d
#E
u+C !FFF3K6Ra5;;=&&(Da!egJ$$&EMM4E!234  [[..v6NqE-m22=Au:?uQx3593C!BKEd	  .
 :r1   rX  r]  c                     |s| S | g}t        |j                               D ]/  \  }}||j                  |       |j                  |d|       1 dj                  |      S )zInverse of _parse_header.

    >>> _encode_header('permessage-deflate',
    ...     {'client_max_window_bits': 15, 'client_no_context_takeover': None})
    'permessage-deflate; client_max_window_bits=15; client_no_context_takeover'
    r   z; )sortedrN   rF   r!   )rX  r]  outrA   rB   s        r%   _encode_headerrb    s_     
%Cu{{}%19JJqM JJ!Q'( & 99S>r1   usernamepasswordc                     t        | t              rt        j                  d|       } t        |t              rt        j                  d|      }t	        |       dz   t	        |      z   S )zEncodes a username/password pair in the format used by HTTP auth.

    The return value is a byte string in the form ``username:password``.

    .. versionadded:: 5.1
    NFC   :)r=   r   unicodedata	normalizer   )rc  rd  s     r%   encode_username_passwordrj    sT     (L)((9(L)((9>D 4>11r1   c                  *    dd l } | j                         S )Nr   )doctestDocTestSuite)rl  s    r%   doctestsrn    s    !!r1   z^(.+):(\d+)$netlocc                     t         j                  |       }|r/|j                  d      }t        |j                  d            }||fS | }d}||fS )zReturns ``(host, port)`` tuple from ``netloc``.

    Returned ``port`` will be ``None`` if not present.

    .. versionadded:: 4.1
    r8   r   N)
_netloc_rerD  rJ  r   )ro  rD  r   ports       r%   r   r   	  sX     V$E{{1~5;;q>" $< $<r1   qsc              #   V   K   | j                         D ]  \  }}|D ]  }||f 
  yw)zgGenerator converting a result of ``parse_qs`` back to name-value pairs.

    .. versionadded:: 5.0
    N)rN   )rs  rA   vsrB   s       r%   	qs_to_qslrv    s/     
 2Aa&L  s   ')z\\(?:([0-3][0-7][0-7])|(.))mc                 F    | d   rt        t        | d   d            S | d   S )Nr8      r   )chrr   )rw  s    r%   _unquote_replacer{  '  s'    t3qtQ<  tr1   c                 t    | t        |       dk  r| S | d   dk7  s| d   dk7  r| S | dd } t        t        |       S )zHandle double quotes and escaping in cookie values.

    This method is copied verbatim from the Python 3.13 standard
    library (http.cookies._unquote) so we don't have to depend on
    non-public interfaces.
    r   r   rN  rS   r8   )r<   _unquote_subr{  )rL  s    r%   _unquote_cookier~  .  sO     	yCFQJts{aesl 	
!BA (!,,r1   cookiec                     i }| j                  t        d            D ]n  }t        d      |v r|j                  t        d      d      \  }}nt        d      |}}|j                         |j                         }}|s|sat        |      ||<   p |S )a[  Parse a ``Cookie`` HTTP header into a dict of name/value pairs.

    This function attempts to mimic browser cookie parsing behavior;
    it specifically does not follow any of the cookie-related RFCs
    (because browsers don't either).

    The algorithm used is identical to that used by Django version 1.9.10.

    .. versionadded:: 4.4.2
    r  r   r8   ru   )r"   r~   rZ   r~  )r  
cookiedictr   rX  r  s        r%   r   r   I  s     Jc#h's8u{{3s8Q/HC 2wC99;		S#-c2JsO ( r1   r+   )cr{   r9  collections.abccollectionsrs   r;  email.utilsr=  	functoolsr   http.clientr   http.cookiesr   resslr   r   rh  urllib.parser   r   r   r	   tornado.escaper
   r   r   tornado.logr   tornado.utilr   r   r|   r   r   r   r   r   r   r   r   r   r   r   TYPE_CHECKINGr   asyncior   unittestrX   r~   r&   abcMutableMappingr(   r   r   r   rV   r   r   r   r   r  r   r   r  r  r  r   r   r  r   r   r8  rA  
namedtupler   compilerC  rE  r   rI  rK  rQ  r,  rb  rj  rn  rq  r   rv  subr}  Matchr{  r~  r   r,   r1   r%   <module>r     s          !  	    C C ; ;  1
 
     
  4?C ?C ? ?h+//00 hV[: [:|	Y 		i 	6 :+& +\+$V +$\,	,
d38nd5c?3U5c?C;O5PP,
 	,^z  00eHSM8C=0120f2hsm 2(3- 2 2PS 2c hsm  &*.B.B
.B Ce$%.B T(^#$	.B
 k".B 
.Bb7979
79 Ce$%79 T(^#$	79
 
79t9c5%!1!183D3DDE990 *;))5 
 2::01 33 3+; 3* +K**6 
 $$GH RC R,= R.
3 
9S$_5 
   c4S>&9 :  F DcN s (2CJ2+0e+<2
2 " RZZ(
 c8C=.@(A "$sDL() huS&[7I.J  rzz89== S -s -s -6 c3h r1   