o
    iF                     @   sd  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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+  m,Z, zd dlm-Z- W n e.y   e/Z-Y nw ee0Z1ej2dk rejj3j4Z4nej5j6j4Z4ej2dkZ7dZ8h dZ9eee:f Z;ee;e<e; e=e;ef ef Z>de?dede?fd d!Z@d"e>defd#d$ZAd%d& ZBd'd( ZCd)d* ZDd+d, ZEd-d. ZFd/d0 ZGd1d2 ZHd3edee?e?f fd4d5ZId6e)fd7d8ZJG d9d: d:eZKdS );    N)Any)Mapping)Text)Union)SimpleLazyObject)FunctionWrapper)config)_SPAN_MEASURED_KEY)trace_utils)get_resolver)user_is_authenticated)	SpanTypes)user)compat)core)
get_logger)stringify_cache_args)parse_form_multipart)parse_form_params)	func_name)from_wsgi_header)Span)JSONDecodeError)   
   r   )   r   r   __django_request>   PUTPOSTPATCHDELETEresourcecachereturnc                 C   s0   t |ddrd| |jf}| S | }| S )zB
    Combine the resource name with the cache prefix (if any)
    
key_prefixN )getattrjoinr$   lower)r!   r"   name r*   Y/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/contrib/internal/django/utils.pyresource_from_cache_prefix8   s
   r,   keysc                 C   sJ   g }t | trt|  }t|S t | ttfr| }t|S | g}t|S )z
    Used for Django cache key normalization.

    If a dict is provided we return a list of keys as text.

    If a list or tuple is provided we convert each element to text.

    If text is provided we convert to text.
    )
isinstancedictlistr-   tupler   )r-   argsr*   r*   r+   quantize_key_valuesE   s   

r3   c                 C   sH   |j }|r|S tt| dd }|r"z|jjjW S  ty!   Y d S w d S )Nurlconf)router   r&   patternregexAttributeError)requestresolver_matchr5   resolverr*   r*   r+   get_django_2_route\   s   r<   c              	   C   sn   |sdS t |dkr|d r| ||d  dS dS t|ddD ]\}}|r4| d|dt|f| q dS )z6Helper to set a span tag as a single value or an arrayNr   r   )start .)len_set_tag_str	enumerater'   str)spanprefixvalueivr*   r*   r+   set_tag_arraym   s   rI   c                 C   s:  t | dr
|  }n>z+d| jv r| jd }n| jd }t| jd }||  r)dndkr4d|d|f}W n tyG   tjd	d
d d}Y nw | j	du rOdS | j	|| j
d}| D ]2\}}t|trt|jtrot|}nt|jtrzt|}ntd||jj  dS t|||< q[d|d d|d |d fS )ze
    Helper to rebuild the original request url

    query string or fragments are not included.
    _get_raw_host	HTTP_HOSTSERVER_NAMESERVER_PORT44380r>   :z#Failed to build Django request hostTexc_infounknownN)schemenetlocpathzOSkipped building Django request uri, %s is SimpleLazyObject wrapping a %s classrT   z://rU   rV   )hasattrrJ   METArC   	is_securer'   	ExceptionlogdebugrT   rV   itemsr.   r   
issubclass	__class__bytes__name__r   ensure_text)r9   hostporturlpartskrH   r*   r*   r+   get_request_uri{   s>   







rg   c           	   
   C   s  |j }zz|j}|stt|dd }||j}t|d dr't|d j}nt|d }d }t	r>t
||}|r>|d| tjjrKd|j |f}n*tjjrR|}n#|r]d|j |f}ntjjrm|j}|rmd||g}d|j |f}|d|j t|d|j t|d	rt|d
|j W n& ty   d|j df}Y n ty   tjd|t|dddd Y nw W |jtkr||_d S d S |jtkr||_w )Nr4   r   
view_classz
http.router%   r?   zdjango.viewzdjango.namespace	app_namesz
django.app404z3Failed to resolve request path %r with path info %r	path_infoznot-setTrQ   )methodr:   r   r&   resolverk   rW   r   rh   DJANGO22r<   rA   r   djangouse_handler_resource_formatr'   use_legacy_resource_format)use_handler_with_url_name_resource_formaturl_name	view_namerI   
namespacesri   Resolver404rZ   r[   r\   r!   REQUEST_DEFAULT_RESOURCE)	pinrD   r9   r!   r:   r;   handlerr5   rs   r*   r*   r+   _set_resolver_tags   sZ   






rz   c                 C   s6   t | tj|_tj|_d|jt	< |
dt| d S )Nr   zdjango.request.class)r
   int_servicer   ro   servicer   WEB	span_type_metricsr	   rA   r   )rx   rD   r9   r*   r*   r+   _before_request_tags   s   
r   c                 C   s   | j tv rzd }t| dr| jn| jd}tdjj	}zL|dkr.t
| jjddd}W |S |dkr@t| jjddd|}W |S |d	v rRt| jjddd}W |S |d
v rdt| jjddd}W |S d }W |S  tyy   tjddd Y |S w d S )Ncontent_typeCONTENT_TYPEzdjango.extract_bodyz!application/x-www-form-urlencodedzUTF-8ignore)errorszmultipart/form-data)zapplication/jsonz	text/json)zapplication/xmlztext/xmlzFailed to parse request bodyTrQ   )rl   _BODY_METHODSrW   r   rX   getr   dispatch_with_resultsheadersrF   r   bodydecoder   jsonloads	xmltodictparserZ   r[   r\   )r9   req_bodyr   r   r*   r*   r+   _extract_body  s8   
	r   c                 C   sv   | j tv r7t| dd r9zt| j}| r#|d || jd< W d S W d S  t	y6   t
jddd Y d S w d S d S )N_bodyr   z
wsgi.inputz$Failed to remake Django request bodyTrQ   )rl   r   r&   ioBytesIOr   seekableseekrX   rZ   r[   r\   )r9   unread_bodyr*   r*   r+   _remake_body  s   
r   r9   c                 C   s>   t r| j}|S i }| j D ]\}}t|}|r|||< q|S )N)rn   r   rX   r]   r   )r9   request_headersheaderrF   r)   r*   r*   r+   _get_request_headers)  s   r   rD   c                 C   s  zgt |dd }|d urazDt|dr|dtt| t |dd }|r=t|ttjfr=|dt| |t	j
t| tjjrOt |dd }|rO|d| W n ty`   tjdd	d
 Y nw t| || |rZ|j}|dt| t|dr|j}t|tr|g}	nt|ttfr|}	nt|dr|jjg}	nd }	t|d|	 t|}
tdjj}|st|}|rt |! ni }i }|j"r|j"! D ]R\}}z>d}d}|# $dD ],}|dkr|$dd\}}|%dr|d dkr|dd n|}n|d| 7 }|d7 }q|||< W q ty   |# ||< Y qw |
}|r1|j&'dr1|d|j&d  7 }t(d|||tj||
|||f	 t |dd }|d u rRt |dd }t(d|d f W |j)t*krg|j+|_)d S d S |j)t*krs|j+|_)w )Nr   is_authenticatedzdjango.user.is_authenticatedpkzdjango.user.idusernamezdjango.user.namez4Error retrieving authentication information for userTrQ   zdjango.response.classtemplate_nametemplatezdjango.response.templatezdjango.after_request_headersr   r>   ;=r   "QUERY_STRING?z!django.after_request_headers.postcontentstreaming_contentz%django.after_request_headers.finalize),r&   rW   rA   rC   r   r.   intuuidUUID_userIDr   ro   include_user_namerZ   r[   r\   rz   status_coder   r   r0   r1   r   r)   rI   rg   r   r   r   rF   r   r/   r]   cookiesOutputStringsplit
startswithrX   r   dispatchr!   rw   rl   )rx   rD   r9   responser   uidr   statusr   template_namesurlr   response_headersresponse_cookiesrf   rH   rG   resultelementkeyrF   raw_urir   r*   r*   r+   _after_request_tags6  s   



(


r   c                   @   s   e Zd ZdZedd ZdS )DjangoViewProxyz
    This custom function wrapper is used to wrap the callback passed to django views handlers (path/re_path/url).
    This allows us to distinguish between wrapped django views and wrapped asgi applications in django channels.
    c                 C   s   | j jS )a  
        DjangoViewProxy.__module__ defaults to ddtrace.contrib.internal.django when a wrapped function does not have
        a __module__ attribute. This method ensures that DjangoViewProxy.__module__ always returns the module
        attribute of the wrapped function or an empty string if this attribute is not available.
        The function Django.urls.path() does not have a __module__ attribute and would require this override
        to resolve the correct module name.
        )__wrapped__
__module__)selfr*   r*   r+   r     s   	zDjangoViewProxy.__module__N)ra   r   __qualname____doc__propertyr*   r*   r*   r+   r     s    r   )Lr   r   typingr   r   r   r   r   ro   django.utils.functionalr   wraptr   ddtracer   ddtrace.constantsr	   ddtrace.contribr
   &ddtrace.contrib.internal.django.compatr   r   ddtrace.extr   r   r   ddtrace.internalr   r   ddtrace.internal.loggerr   ddtrace.internal.utils.formatsr   ddtrace.internal.utils.httpr   r    ddtrace.internal.utils.importlibr   ddtrace.propagation._utilsr   ddtrace.tracer   ddtrace.vendor.xmltodictvendorr   r   ImportError
ValueErrorra   r[   VERSIONurlresolversrv   urls
exceptionsrn   rw   r   r`   _quantize_textr0   r/   _quantize_paramrC   r,   r3   r<   rI   rg   rz   r   r   r   r   r   r   r*   r*   r*   r+   <module>   sj    


9Ey