o
    4ήcT                     @   s~  d dl 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
mZmZmZmZmZmZmZmZ d dlZd dlmZ d dlmZ d dlmZmZmZmZ d dlmZmZm Z m!Z!m"Z" d d	l#m$Z$ ej%d
k rtd dl&m'Z' nd dl
m'Z' erd dl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0 e1dZ2e1dZ3de4de5fddZ6dd e7ddD Z8G dd de j9Z:G dd dZ;dS )    N)TimerHandle)deque)TYPE_CHECKINGCallableDequeListOptionalTupleUnioncast)Config)TRACE_LOG_LEVEL)CLOSE_HEADERHIGH_WATER_LIMITFlowControlservice_unavailable)get_client_addrget_local_addrget_path_with_query_stringget_remote_addris_ssl)ServerState)      )Literal)ASGI3ApplicationASGIReceiveEventASGISendEventHTTPDisconnectEventHTTPRequestEventHTTPResponseBodyEventHTTPResponseStartEvent	HTTPScopes   [ -()<>@,;:[]={} 	\"]s   [ -]status_codereturnc                 C   sH   z
t | j }W n ty   d}Y nw ddt|  d|dgS )N    s	   HTTP/1.1        
)http
HTTPStatusphraseencode
ValueErrorjoinstr)r#   r*    r/   L/tmp/pip-target-vg8gfxp4/lib/python/uvicorn/protocols/http/httptools_impl.py_get_status_line3   s   r1   c                 C   s   i | ]}|t |qS r/   )r1   ).0r#   r/   r/   r0   
<dictcomp>;   s    
r3   d   iX  c                	   @   s\  e Zd Z	d;dededeej ddfddZdej	ddfd	d
Z
dee ddfddZd<ddZd<ddZdee fddZdee defddZdefddZdeddfddZd<ddZdeddfdd Zd<d!d"Zd#eddfd$d%Zd&ed'eddfd(d)Zd<d*d+Zd,eddfd-d.Zd<d/d0Zd<d1d2Zd<d3d4Zd<d5d6Z d<d7d8Z!d<d9d:Z"dS )=HttpToolsProtocolNconfigserver_state_loopr$   c                 C   s   |j s|  || _|j| _|pt | _t	d| _
t	d| _| j | _t| | _|j| _|j| _|j| _d | _|j| _|| _|j| _|j| _d | _d | _d | _d | _d | _t | _d | _ d | _!d| _"d | _#d S )Nzuvicorn.errorzuvicorn.accessF)$loadedloadr6   
loaded_appappasyncioget_event_looplooplogging	getLoggerloggeraccess_loggerhasHandlers
access_log	httptoolsHttpRequestParserparserws_protocol_class	root_pathlimit_concurrencytimeout_keep_alive_tasktimeout_keep_aliver7   connectionstasks	transportflowserverclientschemer   pipelinescopeheadersexpect_100_continuecycle)selfr6   r7   r8   r/   r/   r0   __init__A   s6   
zHttpToolsProtocol.__init__rP   c                 C   sz   | j |  || _t|| _t|| _t|| _t	|rdnd| _
| jjtkr;| jr/d| j nd}| jtd| d S d S )Nhttpsr(   %s:%d -  z%sHTTP connection made)rN   addrP   r   rQ   r   rR   r   rS   r   rT   rB   levelr   log)rZ   rP   prefixr/   r/   r0   connection_madem   s   


z!HttpToolsProtocol.connection_madeexcc                 C   s   | j |  | jjtkr| jrd| j nd}| jtd| | jr)| jjs)d| j_	| jd ur4| jj
  | jd ur>| j  |d u rK| j  |   d | _d S )Nr]   r^   z%sHTTP connection lostT)rN   discardrB   r`   r   rS   ra   rY   response_completedisconnectedmessage_eventsetrQ   resume_writingrP   close_unset_keepalive_if_requiredrH   )rZ   rd   rb   r/   r/   r0   connection_lost|   s   




z!HttpToolsProtocol.connection_lostc                 C      d S Nr/   rZ   r/   r/   r0   eof_received   s   zHttpToolsProtocol.eof_receivedc                 C   s"   | j d ur| j   d | _ d S d S ro   )rL   cancelrp   r/   r/   r0   rl      s   


z.HttpToolsProtocol._unset_keepalive_if_requiredc                 C   sT   g }d }| j D ]\}}|dkrdd |dD }|dkr!| }qd|v r(|S d S )N
   connectionc                 S   s   g | ]}|   qS r/   )lowerstrip)r2   tokenr/   r/   r0   
<listcomp>   s    z2HttpToolsProtocol._get_upgrade.<locals>.<listcomp>   ,s   upgrade)rW   splitrt   )rZ   
connectionupgradenamevaluer/   r/   r0   _get_upgrade   s   zHttpToolsProtocol._get_upgrader{   c                 C   sF   |dkr| j d urdS | jjdkr!d}| j| d}| j| dS )Ns	   websocketTautozUnsupported upgrade request.zNo supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually.F)rI   r6   wsrB   warning)rZ   r{   msgr/   r/   r0   _should_upgrade_to_ws   s   z'HttpToolsProtocol._should_upgrade_to_wsc                 C   s   |   }| |S ro   )r~   r   )rZ   r{   r/   r/   r0   _should_upgrade   s   
z!HttpToolsProtocol._should_upgradedatac                 C   s   |    z	| j| W d S  tjy%   d}| j| | | Y d S  tjy?   | 	 }| 
|r<|   Y d S Y d S w )NzInvalid HTTP request received.)rl   rH   	feed_datarF   HttpParserErrorrB   r   send_400_responseHttpParserUpgrader~   r   handle_websocket_upgrade)rZ   r   r   r{   r/   r/   r0   data_received   s   

zHttpToolsProtocol.data_receivedc                 C   s   | j jtkr| jrd| j nd}| j td| | j|  | jd  }|d| j	dg}| jd D ]\}}||d|d	g7 }q1|
d	 | j| j| jd
}|| j |d| | j| d S )Nr]   r^   z%sUpgrading to WebSocketmethodr&   s    HTTP/1.1
rW      : r'   )r6   r7   r%   )rB   r`   r   rS   ra   rN   re   rV   r+   urlappendrI   r6   r7   rc   rP   r   r-   set_protocol)rZ   rb   r   outputr|   r}   protocolr/   r/   r0   r      s   
z*HttpToolsProtocol.handle_websocket_upgrader   c              	   C   s~   t d g}| jjD ]\}}||d|dg q	|ddtt|d d dd|dg | jd	| | j
  d S )	Ni  r   r'   s)   content-type: text/plain; charset=utf-8
s   content-length: asciis   connection: close
r%   )STATUS_LINEr7   default_headersextendr.   lenr+   rP   writer-   rk   )rZ   r   contentr|   r}   r/   r/   r0   r      s   
	z#HttpToolsProtocol.send_400_responsec              	   C   sB   d| _ d| _g | _d| jjddd| j| j| j| j| jd| _	d S )Nr%   Fr(   z2.3)versionspec_version1.1)typeasgihttp_versionrR   rS   rT   rJ   rW   )
r   rX   rW   r6   asgi_versionrR   rS   rT   rJ   rV   rp   r/   r/   r0   on_message_begin   s   z"HttpToolsProtocol.on_message_beginr   c                 C   s   |  j |7  _ d S ro   )r   )rZ   r   r/   r/   r0   on_url   s   zHttpToolsProtocol.on_urlr|   r}   c                 C   s6   |  }|dkr|  dkrd| _| j||f d S )Ns   expects   100-continueT)rt   rX   rW   r   )rZ   r|   r}   r/   r/   r0   	on_header   s   zHttpToolsProtocol.on_headerc           
      C   s  | j  }| j  }|d| jd< |dkr|| jd< | j  r&|  r&d S t| j	}|j
}|d}d|v r>tj|}|| jd< || jd< |jpLd| jd	< | jd urpt| j| jkset| j| jkrpt}d
}| j| n| j}| j}t| j| j| j| j| j| j| jjt  | j!|dk| j"d| _|d u s|j#r| j$%| j&|}	|	'| jj( | j)|	 d S | j*  | j+,| j|f d S )Nr   r   r   r   %pathraw_pathr%   query_stringzExceeded concurrency limit.z1.0)rV   rP   rQ   rB   rC   rE   r   rh   rX   
keep_aliveon_response)-rH   get_http_version
get_methoddecoderV   should_upgrader   rF   	parse_urlr   r   urllibparseunquotequeryrK   r   rN   rO   r   rB   r   r<   rY   RequestResponseCyclerP   rQ   rC   rE   r7   r   r=   EventrX   on_response_completerf   r?   create_taskrun_asgiadd_done_callbackre   r_   pause_readingrU   
appendleft)
rZ   r   r   
parsed_urlr   r   r<   messageexisting_cycletaskr/   r/   r0   on_headers_complete   sX   







z%HttpToolsProtocol.on_headers_completebodyc                 C   sX   | j  r	|  s| jjrd S | j j|7  _t| jjtkr$| j	  | jj
  d S ro   )rH   r   r   rY   rf   r   r   r   rQ   r   rh   ri   )rZ   r   r/   r/   r0   on_body0  s   
zHttpToolsProtocol.on_bodyc                 C   s6   | j  r	|  s| jjrd S d| j_| jj  d S )NF)rH   r   r   rY   rf   	more_bodyrh   ri   rp   r/   r/   r0   on_message_complete:  s   z%HttpToolsProtocol.on_message_completec                 C   s   | j  jd7  _| j rd S |   | j| j| j| _	| j
  | jrD| j \}}| j||}|| jj | j| d S d S )N   )r7   total_requestsrP   
is_closingrl   r?   
call_laterrM   timeout_keep_alive_handlerrL   rQ   resume_readingrU   popr   r   r   rO   re   r_   )rZ   rY   r<   r   r/   r/   r0   r   B  s   

z&HttpToolsProtocol.on_response_completec                 C   s,   | j du s	| j jr| j  dS d| j _dS )zG
        Called by the server to commence a graceful shutdown.
        NF)rY   rf   rP   rk   r   rp   r/   r/   r0   shutdownZ  s   zHttpToolsProtocol.shutdownc                 C      | j   dS )z\
        Called by the transport when the write buffer exceeds the high water mark.
        N)rQ   pause_writingrp   r/   r/   r0   r   c     zHttpToolsProtocol.pause_writingc                 C   r   )z_
        Called by the transport when the write buffer drops below the low water mark.
        N)rQ   rj   rp   r/   r/   r0   rj   i  r   z HttpToolsProtocol.resume_writingc                 C   s   | j  s| j   dS dS )zk
        Called on a keep-alive connection if no new data is received after a short
        delay.
        N)rP   r   rk   rp   r/   r/   r0   r   o  s   
z,HttpToolsProtocol.timeout_keep_alive_handlerro   r$   N)#__name__
__module____qualname__r   r   r   r=   AbstractEventLoopr[   	Transportrc   	Exceptionrm   rq   rl   bytesr~   boolr   r   r   r   r.   r   r   r   r   r   r   r   r   r   r   rj   r   r/   r/   r/   r0   r5   @   sH    
,






4




	
r5   c                   @   s   e Zd Zdddejdedejdejdede	e
eef  d	ejd
ededed fddZdddZd ddZd!ddZd"ddZdS )#r   rV   r"   rP   rQ   rB   rC   rE   r   rh   rX   r   r   ).Nc                 C   sp   || _ || _|| _|| _|| _|| _|| _|| _|| _d| _	|
| _
|	| _d| _d| _d| _d| _d | _d| _d S )NFr%   Tr   )rV   rP   rQ   rB   rC   rE   r   rh   r   rg   r   waiting_for_100_continuer   r   response_startedrf   chunked_encodingexpected_content_length)rZ   rV   rP   rQ   rB   rC   rE   r   rh   rX   r   r   r/   r/   r0   r[   y  s$   
zRequestResponseCycle.__init__r<   r   r$   Nc              
      s^  zz|| j | j| jI d H }W n, ty< } z d}| jj||d | js-|  I d H  n| j	  W Y d }~nId }~ww |d urPd}| j|| | j	  n9| jsf| j
sfd}| j| |  I d H  n3| js| j
sd}| j| | j	  W dd | _d S W dd | _d S W dd | _d S W dd | _d S W dd | _d S W dd | _d S dd | _w )NzException in ASGI application
)exc_infoz4ASGI callable should return None, but returned '%s'.z1ASGI callable returned without starting response.z3ASGI callable returned without completing response.c                   S   rn   ro   r/   r/   r/   r/   r0   <lambda>  s    z/RequestResponseCycle.run_asgi.<locals>.<lambda>)rV   receivesendBaseExceptionrB   errorr   send_500_responserP   rk   rg   rf   r   )rZ   r<   resultrd   r   r/   r/   r0   r     sH   
 
zRequestResponseCycle.run_asgic                    sB   ddddgd}|  |I d H  dddd	}|  |I d H  d S )
Nhttp.response.starti  )s   content-types   text/plain; charset=utf-8)rs      close)r   statusrW   http.response.bodys   Internal Server ErrorFr   r   r   )r   )rZ   response_start_eventresponse_body_eventr/   r/   r0   r     s   z&RequestResponseCycle.send_500_responser   r   c                    s  |d }| j jr| js| j  I d H  | jrd S | js|dkr(d}t|| td|}d| _d| _|d }| jt	|
dg  }t| jd v rRt|vrR|tg }| jrl| jd	t| j| jd
 t| j| jd | t| g}|D ]U\}}t|rtdt|rtd| }|dkr| jd u rt| | _d| _n|dkr| dkrd| _d| _n|dkr| dkrd| _||d|dg qs| jd u r| jd
 dkr|dvrd| _|d |d | jd | d S | j!s|dkrd}t|| tt"|
dd}	|
dd}
| jd
 dkrd| _n@| jrB|	r.dt#|	 |	dg}ng }|
s8|d | jd | nt#|	}|| jkrPtd |  j|8  _| j|	 |
s| jdkrjtd!d| _!| j$%  | js{| j&  | '  d S d S d"}t|| )#Nr   r   z:Expected ASGI message 'http.response.start', but got '%s'.r!   TFr   rW   z%s - "%s %s HTTP/%s" %dr   r   zInvalid HTTP header name.zInvalid HTTP header value.s   content-lengths   transfer-encodings   chunkedr   rs   r   r   r'   HEAD)   i0  s   transfer-encoding: chunked
r%   r   z9Expected ASGI message 'http.response.body', but got '%s'.r   r   s   %x
s   0

z+Response content longer than Content-Lengthz,Response content shorter than Content-LengthzDUnexpected ASGI message '%s' sent, after response already completed.)(rQ   write_pausedrg   drainr   RuntimeErrorr   r   r   listgetr   rV   rE   rC   infor   r   r   	HEADER_REsearchHEADER_VALUE_RErt   r   intr   r   r   r   r   rP   r   r-   rf   r   r   rh   ri   rk   r   )rZ   r   message_typer   r#   rW   r   r|   r}   r   r   	num_bytesr/   r/   r0   r     s   











zRequestResponseCycle.sendr   c                    s   | j r| j s| jd d| _ | js*| js*| j  | j	 I d H  | j
  | js0| jr6ddi}|S d| j| jd}d| _|S )Ns   HTTP/1.1 100 Continue

Fr   zhttp.disconnectzhttp.requestr   r%   )r   rP   r   r   rg   rf   rQ   r   rh   waitclearr   r   )rZ   r   r/   r/   r0   r   =  s"   

	zRequestResponseCycle.receive)r<   r   r$   Nr   )r   r   r$   N)r$   r   )r   r   r   r=   r   r   r@   Loggerr   r   r	   r   r   r   r[   r   r   r   r   r/   r/   r/   r0   r   x  s8    	


(

nr   )<r=   r(   r@   resysr   asyncio.eventsr   collectionsr   typingr   r   r   r   r   r	   r
   r   rF   uvicorn.configr   uvicorn.loggingr   #uvicorn.protocols.http.flow_controlr   r   r   r   uvicorn.protocols.utilsr   r   r   r   r   uvicorn.serverr   version_infotyping_extensionsr   asgiref.typingr   r   r   r   r   r    r!   r"   compiler   r   r   r   r1   ranger   Protocolr5   r   r/   r/   r/   r0   <module>   s<    (
(

  :