o
    iuA                     @   s  U d dl mZ d dlmZ d dlmZ d dlm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mZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dlm!Z! d dlm"Z" d dl#m$Z$ d dl%m&Z& e
'dZ(e
'dZ)erd dl*m+Z, d dl-m.Z. d dl-m/Z/ d dl0m1Z1 ed Z2eg ed  f Z3e4e5Z6e& d!ee7 d"ee7 fd#d$Z8d%e7d"e7fd&d'Z9d(e7d)e
jd"ee:e7f fd*d+Z;	dYd%e7d)e
jd(ee7 d"ee7e:f fd,d-Z<d.e=e:d/f d0e7d"e:fd1d2Z>d%e7d3ed"e3fd4d5Z?d6d7 Z@e& d8e=ee7e7f d"e7fd9d:ZAd;d< ZBG d=d> d>eCZDefd%e7d?eEd"e2fd@dAZFd%e7d"ejGfdBdCZHdaIee7 eJdD< daKee7 eJdE< dFZLdGe7dHe7d"e7fdIdJZMdKe7dHe7d"e7fdLdMZNdNe7d"eOe7ee7ePe7 f f fdOdPZQdYdNe7dQeeO d"eOe7ef fdRdSZReG dTdU dUZSdVePeS d"e=e:eOf fdWdXZTdS )Z    )contextmanager)	dataclass)encode_noop)loadsN)TYPE_CHECKING)Any)Callable)ContextManager)	Generator)Optional)Pattern)Union)parse)_USER_ID_KEY)unpatched_open)BLOCKED_RESPONSE_HTML)BLOCKED_RESPONSE_JSON)DEFAULT_TIMEOUT)SAMPLING_DECISION_TRACE_TAG_KEY)W3C_TRACESTATE_ORIGIN_KEY)W3C_TRACESTATE_PARENT_ID_KEY)$W3C_TRACESTATE_SAMPLING_PRIORITY_KEY)_get_metas_to_propagate)cachedz,|;|~|[^\x20-\x7E]+z,| |=|[^\x20-\x7E]+HTTPConnectionHTTPSConnectionUDSHTTPConnection)r   r   r   httplib.HTTPConnectionheader_namereturnc                 C   s   | dur
|    S dS )z
    Normalizes an header name to lower case, stripping all its leading and trailing white spaces.
    :param header_name: the header name to normalize
    :type header_name: str
    :return: the normalized header name
    :rtype: str
    N)striplower)r!    r%   O/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/utils/http.pynormalize_header_name1   s   	r'   urlc                 C   s4   |  d\}}}| d\}}}|s|S || | S )z
    Strips the query string from a URL for use as tag in spans.
    :param url: The URL to be stripped
    :return: The given URL without query strings
    #?)	partition)r(   hqsfsfh_r%   r%   r&   strip_query_string=   s
   r1   query_string query_string_obfuscation_patternc                 C   s$   t | tr| n| d}|d|S )Nutf-8s
   <redacted>)
isinstancebytesencodesub)r2   r3   bytes_queryr%   r%   r&   redact_query_stringJ   s   r:   c                 C   s   t | }d }|rt||}n	|jrt|j|}|d ur?t|dkr?|d d |f |dd   }tdd |D }t|| S | S )N      c                 s   s(    | ]}t |tr|n|d V  qdS )r4   N)r5   r6   r7   ).0xr%   r%   r&   	<genexpr>\   s   & zredact_url.<locals>.<genexpr>)r   urlparser:   querylentuple
urlunsplit)r(   r3   r2   partsredacted_queryredacted_partsbytes_redacted_partsr%   r%   r&   
redact_urlO   s   

rI   
components.original_urlc                 C   s   | \}}}}}}|rd||f }|s|r2|dd dkr2|r*|dd dkr*d| }d|p.d|f }|r:d	||f }|sD|rJ|d
 dv rJd||f }|sT|rZ|d
 dv rZd||f }|S )zK
    Adaptation from urlunsplit and urlunparse, using bytes components
    s   %s;%sN   s   //      /s   //%s%s    s   %s:%s)r*      ?s   %s?%s)r)      #s   %s#%sr%   )rJ   rK   schemenetlocr(   paramsrA   fragmentr%   r%   r&   rD   c   s   rD   kwargsc                    s*   t dttd ddf f fdd}|S )a  Create a connector context manager for the given URL.

    This function returns a context manager that wraps a connection object to
    perform HTTP requests against the given URL. Extra keyword arguments can be
    passed to the underlying connection object, if needed.

    Example::
        >>> connect = connector("http://localhost:8080")
        >>> with connect() as conn:
        ...     conn.request("GET", "/")
        ...     ...
    r"   )r    zhttplib.HTTPSConnectionNc                  3   s$    t fi  } | V  |   d S N)get_connectionclose)
connectionrW   r(   r%   r&   _connector_context   s   z%connector.<locals>._connector_context)r   r
   r   )r(   rW   r]   r%   r\   r&   	connectorw   s   $r^   c           	   	   C   s8  g }| j d ur|dt| j  | jr#|dtttd| jf | j	t
}|r8|dttd|f | j	t}|rM|dttd|f tdd |D }t| D ]<\}}|t
tfvr|dd}dttd|fttd|f}|t| }|d	ks|| |t|7 }qZtd
| qZd|S )Nz{}:{}r0   zt.dm:{}zt.usr.id:{}c                 s   s    | ]}t |V  qd S rX   )rB   )r=   ir%   r%   r&   r?      s    z)w3c_get_dd_list_member.<locals>.<genexpr>z_dd.p.zt.   zKtracestate would exceed 256 char limit with tag: %s. Tag will not be added.;)sampling_priorityappendformatr   	dd_originr   w3c_encode_tag)_W3C_TRACESTATE_INVALID_CHARS_REGEX_VALUE_metagetr   r   sumr   replace'_W3C_TRACESTATE_INVALID_CHARS_REGEX_KEYrB   logdebugjoin)	contexttagssampling_decisionusr_idcurrent_tags_lenkvnext_tagpotential_current_tags_lenr%   r%   r&   w3c_get_dd_list_member   sB   


ry   argsc                 C   s"   | \}}}| ||}|ddS )N=~)r8   rk   )rz   patternreplacementtag_valr%   r%   r&   rf      s   
rf   c                 C   sF   d t|}d| v r| dd| dS | rd| d|  S d| S )Nz
{}:{:016x}zdd=ra   ,)rd   r   rk   )
tracestatespan_idp_memberr%   r%   r&   w3c_tracestate_add_p   s   
r   c                   @   s>   e Zd ZdZg dZdddZedd Zdd	 Zd
d Z	dS )Responsea  
    Custom API Response object to represent a response from calling the API.

    We do this to ensure we know expected properties will exist, and so we
    can call `resp.read()` and load the body once into an instance before we
    close the HTTPConnection used for the request.
    statusbodyreasonmsgNc                 C   s   || _ || _|| _|| _d S rX   r   )selfr   r   r   r   r%   r%   r&   __init__   s   
zResponse.__init__c                 C   s&   | |j | t|ddt|dddS )ad  
        Build a ``Response`` from the provided ``HTTPResponse`` object.

        This function will call `.read()` to consume the body of the ``HTTPResponse`` object.

        :param resp: ``HTTPResponse`` object to build the ``Response`` from
        :type resp: ``HTTPResponse``
        :rtype: ``Response``
        :returns: A new ``Response``
        r   Nr   r   )r   readgetattr)clsrespr%   r%   r&   from_http_response   s   

zResponse.from_http_responsec              	   C   s   z4| j }|std|  W dS t|tst|dr|d}t|dr0|dr0td W dS t|W S  t	t
fyH   tjd|d	d
 Y dS w )z0Helper to parse the body of this request as JSONz"Empty reply from Datadog Agent, %rNdecoder4   
startswithOKzUCannot parse Datadog Agent response. This occurs because Datadog agent is out of datez/Unable to parse Datadog Agent JSON response: %rT)exc_info)r   rm   rn   r5   strhasattrr   r   r   
ValueError	TypeError)r   r   r%   r%   r&   get_json   s   


zResponse.get_jsonc                 C   s   d | jj| j| j| j| jS )Nz6{0}(status={1!r}, body={2!r}, reason={3!r}, msg={4!r}))rd   	__class____name__r   r   r   r   )r   r%   r%   r&   __repr__  s   zResponse.__repr__)NNNN)
r   
__module____qualname____doc__	__slots__r   classmethodr   r   r   r%   r%   r%   r&   r      s    

r   timeoutc                 C   s   t | }|jpd}|jpd}ddlm} ddlm} ddlm} |jdkr/|j	||j
||dS |jd	kr>|j	||j
||dS |jd
krL||||j
|dS td|j )z+Return an HTTP connection to the given URL. /r   r   r   r   https)	base_pathr   httpunix)r   zUnsupported protocol '%s')
verify_urlhostnamepathddtrace.internal.httpr   r   ddtrace.internal.udsr   rS   with_base_pathportr   )r(   r   parsedr   r   r   r   r   r%   r%   r&   rY     s   




rY   c                 C   sn   t | }d}|j|vrtd|j| d|f |jdv r'|js'td|  |jdkr5|js5td|  |S )zValidates that the given URL can be used as an intake
    Returns a parse.ParseResult.
    Raises a ``ValueError`` if the URL cannot be used as an intake
    )r   r   r   z@Unsupported protocol '%s' in intake URL '%s'. Must be one of: %sz, )r   r   z#Invalid hostname in intake URL '%s'r   z$Invalid file path in intake URL '%s')r   r@   rS   r   ro   r   r   )r(   r   schemesr%   r%   r&   r   $  s   

r   _HTML_BLOCKED_TEMPLATE_CACHE_JSON_BLOCKED_TEMPLATE_CACHEz[security_response_id]templatesecurity_response_idc                 C   s   |  t|S rX   )rk   _RESPONSE_ID_TEMPLATE)r   r   r%   r%   r&   _format_template=  s   r   accept_header_valuec              
   C   s  d}| rd|   v rd}|rtrtt|S |strtt|S |r&td}ntd}|rqz&t|d}| }W d    n1 sBw   Y  |rL|an|at||W S  tt	fyp } zt
d|t| W Y d }~nd }~ww |rztatt|S tatt|S )NFz	text/htmlT$DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML$DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSONrz(Could not load custom template at %s: %s)r$   r   r   r   osgetenvopenr   OSErrorIOErrorrm   warningr   r   r   )r   r   need_html_templatetemplate_pathtemplate_filecontenter%   r%   r&   _get_blocked_templateA  s8   





r   r   c                 C   s   |  dd}t }|dD ]6}|d\}}}|rDt|}t|}||d}|du r3|||< qt|tr>|	| q||g||< q|S )2Return a dict of form data after HTTP form parsing+ &r{   N)
rk   dictsplitr+   r   unquoteri   r5   listrc   )r   body_paramsreq_bodyitemkeyequalval
prev_valuer%   r%   r&   parse_form_paramsk  s   



r   headersc                    sf   ddl }ddl ddlm  fdd|dur1|dp#|d}|d|| f }|S i S )	r   r   N)parse_qsc                    s   |   rfdd|  D }|S | d}|dv r# |  }|S |dv r9dd lm  m} ||  }|S |dv rE|  }|S |dv rO|  }|S d	}|S )
Nc                    s&   i | ]}|j d | dd |qS )namezcontent-disposition)failobjheader)	get_paramget_filename)r=   part)parse_messager%   r&   
<dictcomp>  s    z?parse_form_multipart.<locals>.parse_message.<locals>.<dictcomp>Content-Type)zapplication/jsonz	text/json)zapplication/xmlztext/xmlr   )zapplication/x-url-encodedz!application/x-www-form-urlencoded)z
text/plainNr   )is_multipartget_payloadri   r   ddtrace.vendor.xmltodictvendor	xmltodictr   )r   rescontent_typer   jsonr   r   r%   r&   r     s*   

z+parse_form_multipart.<locals>.parse_messager   zcontent-typez%MIME-Version: 1.0
Content-Type: %s
%s)emailr   urllib.parser   ri   message_from_string)r   r   r   r   r   r%   r   r&   parse_form_multipart~  s   r   c                   @   s6   e Zd ZU eed< eed< eeef ed< eed< dS )FormDatar   filenamedatar   N)r   r   r   r   __annotations__r   r6   r%   r%   r%   r&   r     s
   
 r   rE   c           
      C   s   ddl m} ddlm} ddlm} |d}|d= | D ]}||j|jt}|j	dd|j
|jd |d= || q|j|d	d
\}}}	|	tdd |  D fS )Nr   )MIMEApplication)MIMEMultipart)HTTPz	form-datazMIME-VersionzContent-Disposition)r   r   )policys   

c                 s   s    | ]}| d V  qdS )z: N)r   )r=   r0   r%   r%   r&   r?     s    zmultipart.<locals>.<genexpr>)email.mime.applicationr   email.mime.multipartr   email.policyr   r   r   r   
add_headerr   r   attachas_bytesr+   r   r   
splitlines)
rE   r   r   r   r   r   appr   r0   r   r%   r%   r&   	multipart  s   r  rX   )U
contextlibr   dataclassesr   email.encodersr   r   r   loggingr   retypingr   r   r   r	   r
   r   r   r   urllibr   ddtrace.constantsr   ddtrace.internal._unpatchedr   r   ddtrace.internal.constantsr   r   r   r   r   r   r   ddtrace.internal.utilsr   ddtrace.internal.utils.cacher   compilerg   rl   http.clientclienthttplibr   r   r   r   r   ConnectionType	Connector	getLoggerr   rm   r   r'   r1   r6   r:   rI   rC   rD   r^   ry   rf   r   objectr   floatrY   ParseResultr   r   r   r   r   r   r   r   r   r   r   r   r  r%   r%   r%   r&   <module>   s    


 

,
D&*$$"