U
    R¹Öh-U  ã                   @  s@  d dl m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 d dlZd dlmZmZmZmZmZm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 )d¡Z*e )d¡Z+dddœdd„Z,dd„ e-ddƒD ƒZ.G dd„ dej/ƒZ0G dd„ dƒZ1dS )é    )ÚannotationsN)ÚTimerHandle)Údeque)ÚAnyÚCallableÚLiteralÚcast)ÚASGI3ApplicationÚASGIReceiveEventÚASGISendEventÚHTTPRequestEventÚHTTPResponseStartEventÚ	HTTPScope)Ú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)ÚServerStates   [ -()<>@,;:[]={} 	\"]s	   [ -
-]ÚintÚbytes)Ústatus_codeÚreturnc                 C  sJ   zt  | ¡j ¡ }W n tk
r,   d}Y nX d dt| ƒ ¡ d|dg¡S )Nó    s	   HTTP/1.1 ó    ó   
)ÚhttpZ
HTTPStatusÚphraseÚencodeÚ
ValueErrorÚjoinÚstr)r   r#   © r(   úK./venv/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.pyÚ_get_status_line    s
    
r*   c                 C  s   i | ]}|t |ƒ“qS r(   )r*   )Ú.0r   r(   r(   r)   Ú
<dictcomp>(   s      r,   éd   iX  c                   @  sh  e Zd ZdDddddddœdd	„Zd
ddœdd„Zdddœdd„Zddœdd„Zddœdd„Zddœdd„Zddœdd„Z	ddœdd„Z
ddœdd „Zd!dd"œd#d$„Zddœd%d&„Zd'dd(œd)d*„Zddœd+d,„Zd!dd-œd.d/„Zd!d!dd0œd1d2„Zddœd3d4„Zd!dd5œd6d7„Zddœd8d9„Zddœd:d;„Zddœd<d=„Zddœd>d?„Zddœd@dA„ZddœdBdC„ZdS )EÚHttpToolsProtocolNr   r   zdict[str, Any]z asyncio.AbstractEventLoop | NoneÚNone)ÚconfigÚserver_stateÚ	app_stateÚ_loopr   c                 C  s  |j s| ¡  || _|j| _|p&t ¡ | _t 	d¡| _
t 	d¡| _| j ¡ | _t | ¡| _z| jjdd W n tk
r€   Y nX |j| _|j| _|j| _|| _d | _|j| _|| _|j| _|j| _d | _d | _d | _d | _d | _ t!ƒ | _"d | _#d | _$d| _%d | _&d S )Nzuvicorn.errorzuvicorn.accessT)Zlenient_data_after_closeF)'ZloadedÚloadr0   Z
loaded_appÚappÚasyncioZget_event_loopÚloopÚloggingZ	getLoggerÚloggerÚaccess_loggerZhasHandlersÚ
access_logÚ	httptoolsZHttpRequestParserÚparserZset_dangerous_lenienciesÚAttributeErrorÚws_protocol_classÚ	root_pathÚlimit_concurrencyr2   Útimeout_keep_alive_taskÚtimeout_keep_aliver1   ÚconnectionsÚtasksÚ	transportÚflowÚserverÚclientÚschemer   ÚpipelineÚscopeÚheadersÚexpect_100_continueÚcycle)Úselfr0   r1   r2   r3   r(   r(   r)   Ú__init__,   s@    zHttpToolsProtocol.__init__úasyncio.Transport)rF   r   c                 C  sv   | j  | ¡ || _t|ƒ| _t|ƒ| _t|ƒ| _t	|ƒr<dnd| _
| jjtkrr| jr^d| j nd}| j td|¡ d S )NZhttpsr"   ú%s:%d - Ú z%sHTTP connection made)rD   ÚaddrF   r   rG   r   rH   r   rI   r   rJ   r9   Úlevelr   Úlog)rP   rF   Úprefixr(   r(   r)   Úconnection_madeb   s    


z!HttpToolsProtocol.connection_madezException | None)Úexcr   c                 C  s    | j  | ¡ | jjtkr<| jr(d| j nd}| j td|¡ | jrR| jjsRd| j_	| jd k	rh| jj
 ¡  | jd k	r|| j ¡  |d kr–| j ¡  |  ¡  d | _d S )NrS   rT   z%sHTTP connection lostT)rD   Údiscardr9   rV   r   rI   rW   rO   Úresponse_completeÚdisconnectedÚmessage_eventÚsetrG   Úresume_writingrF   ÚcloseÚ_unset_keepalive_if_requiredr=   )rP   rZ   rX   r(   r(   r)   Úconnection_lostq   s    



z!HttpToolsProtocol.connection_lost©r   c                 C  s   d S ©Nr(   ©rP   r(   r(   r)   Úeof_received„   s    zHttpToolsProtocol.eof_receivedc                 C  s   | j d k	r| j  ¡  d | _ d S re   )rB   Úcancelrf   r(   r(   r)   rb   ‡   s    

z.HttpToolsProtocol._unset_keepalive_if_requiredzbytes | Nonec                 C  sT   g }d }| j D ]4\}}|dkr2dd„ | d¡D ƒ}|dkr| ¡ }qd|krP|S d S )Nó
   connectionc                 S  s   g | ]}|  ¡  ¡ ‘qS r(   )ÚlowerÚstrip)r+   Útokenr(   r(   r)   Ú
<listcomp>‘   s     z2HttpToolsProtocol._get_upgrade.<locals>.<listcomp>ó   ,s   upgrade)rM   Úsplitrj   )rP   Z
connectionÚupgradeÚnameÚvaluer(   r(   r)   Ú_get_upgradeŒ   s    
zHttpToolsProtocol._get_upgradeÚboolc                 C  s   | j d krdS dS )NFT)r?   rf   r(   r(   r)   Ú_should_upgrade_to_ws˜   s    
z'HttpToolsProtocol._should_upgrade_to_wsc                 C  s(   | j  d¡ |  ¡ s$d}| j  |¡ d S )NzUnsupported upgrade request.z…No supported WebSocket library detected. Please use "pip install 'uvicorn[standard]'", or install 'websockets' or 'wsproto' manually.)r9   Úwarningru   )rP   Úmsgr(   r(   r)   Ú_unsupported_upgrade_warning   s    z.HttpToolsProtocol._unsupported_upgrade_warningc                 C  s   |   ¡ }|dko|  ¡ S )Ns	   websocket)rs   ru   )rP   rp   r(   r(   r)   Ú_should_upgrade£   s    z!HttpToolsProtocol._should_upgrader   )Údatar   c                 C  s~   |   ¡  z| j |¡ W n` tjk
rJ   d}| j |¡ |  |¡ Y d S  tjk
rx   |  	¡ rl|  
¡  n|  ¡  Y nX d S )NzInvalid HTTP request received.)rb   r=   Z	feed_datar<   ZHttpParserErrorr9   rv   Úsend_400_responseZHttpParserUpgradery   Úhandle_websocket_upgraderx   )rP   rz   rw   r(   r(   r)   Údata_received§   s    

zHttpToolsProtocol.data_receivedc                 C  sÈ   | j jtkr0| jrd| j nd}| j  td|¡ | j | ¡ | jd  ¡ }|d| j	dg}| jd D ]\}}||d|d	g7 }qb| 
d	¡ | j| j| j| jd
}| | j¡ | d |¡¡ | j |¡ d S )NrS   rT   z%sUpgrading to WebSocketÚmethodr    s    HTTP/1.1
rM   ó   : r!   )r0   r1   r2   r   )r9   rV   r   rI   rW   rD   r[   rL   r$   ÚurlÚappendr?   r0   r1   r2   rY   rF   r}   r&   Zset_protocol)rP   rX   r~   Úoutputrq   rr   Zprotocolr(   r(   r)   r|   ·   s"    
ýz*HttpToolsProtocol.handle_websocket_upgrader'   )rw   r   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_LINEr1   Údefault_headersÚextendr'   Úlenr$   rF   Úwriter&   ra   )rP   rw   Úcontentrq   rr   r(   r(   r)   r{   Ë   s    
ûÿ	z#HttpToolsProtocol.send_400_responsec              
   C  sJ   d| _ d| _g | _d| jjddœd| j| j| j| j| j| j	 
¡ dœ	| _d S )Nr   Fr"   z2.3)ÚversionZspec_versionú1.1)	ÚtypeZasgiÚhttp_versionrH   rI   rJ   r@   rM   Ústate)r€   rN   rM   r0   Zasgi_versionrH   rI   rJ   r@   r2   ÚcopyrL   rf   r(   r(   r)   Úon_message_beginÛ   s    ÷z"HttpToolsProtocol.on_message_begin)r€   r   c                 C  s   |  j |7  _ d S re   )r€   )rP   r€   r(   r(   r)   Úon_urlì   s    zHttpToolsProtocol.on_url)rq   rr   r   c                 C  s6   |  ¡ }|dkr"|  ¡ dkr"d| _| j ||f¡ d S )Ns   expects   100-continueT)rj   rN   rM   r   )rP   rq   rr   r(   r(   r)   Ú	on_headerï   s    zHttpToolsProtocol.on_headerc                 C  s¤  | j  ¡ }| j  ¡ }| d¡| jd< |dkr6|| jd< | j  ¡ rL|  ¡ rLd S t | j	¡}|j
}| d¡}d|kr|tj |¡}| j| }| j d¡| }|| jd< || jd< |jp²d| jd	< | jd k	rút| jƒ| jksät| jƒ| jkrút}d
}	| j |	¡ n| j}| j}
t| j| j| j| j| j| j| jj t! "¡ | j#|dk| j$d| _|
d ksT|
j%r„| j& '| j (|¡¡}| )| jj*¡ | j +|¡ n| j ,¡  | j- .| j|f¡ d S )Nrƒ   r~   r‹   r   ú%ÚpathÚraw_pathr   Zquery_stringzExceeded concurrency limit.z1.0©rL   rF   rG   r9   r:   r;   r…   r^   rN   Ú
keep_aliveÚon_response)/r=   Zget_http_versionZ
get_methodÚdecoderL   Úshould_upgradery   r<   Z	parse_urlr€   r”   ÚurllibÚparseZunquoter@   r$   ZqueryrA   r‡   rD   rE   r   r9   rv   r5   rO   ÚRequestResponseCyclerF   rG   r:   r;   r1   r…   r6   ÚEventrN   Úon_response_completer\   r7   Úcreate_taskÚrun_asgiÚadd_done_callbackr[   rU   Úpause_readingrK   Ú
appendleft)rP   r   r~   Z
parsed_urlr•   r”   Ú	full_pathZfull_raw_pathr5   ÚmessageZexisting_cycleÚtaskr(   r(   r)   Úon_headers_completeõ   s\    







ÿÿõ
z%HttpToolsProtocol.on_headers_complete)Úbodyr   c                 C  sX   | j  ¡ r|  ¡ s| jjrd S | j j|7  _t| jjƒtkrH| j 	¡  | jj
 ¡  d S re   )r=   rš   ry   rO   r\   r©   r‡   r   rG   r£   r^   r_   )rP   r©   r(   r(   r)   Úon_body*  s    
zHttpToolsProtocol.on_bodyc                 C  s6   | j  ¡ r|  ¡ s| jjrd S d| j_| jj ¡  d S )NF)r=   rš   ry   rO   r\   Ú	more_bodyr^   r_   rf   r(   r(   r)   Úon_message_complete2  s    z%HttpToolsProtocol.on_message_completec                 C  sŠ   | j  jd7  _| j ¡ rd S |  ¡  | j ¡  | jrr| j ¡ \}}| j	 
| |¡¡}| | jj¡ | j |¡ n| j	 | j| j¡| _d S )Né   )r1   Ztotal_requestsrF   Ú
is_closingrb   rG   Úresume_readingrK   Úpopr7   r    r¡   r¢   rE   r[   rU   Z
call_laterrC   Útimeout_keep_alive_handlerrB   )rP   rO   r5   r§   r(   r(   r)   rŸ   8  s    

 ÿz&HttpToolsProtocol.on_response_completec                 C  s*   | j dks| j jr| j ¡  nd| j _dS )zG
        Called by the server to commence a graceful shutdown.
        NF)rO   r\   rF   ra   r—   rf   r(   r(   r)   ÚshutdownP  s    zHttpToolsProtocol.shutdownc                 C  s   | j  ¡  dS )z\
        Called by the transport when the write buffer exceeds the high water mark.
        N)rG   Úpause_writingrf   r(   r(   r)   r³   Y  s    zHttpToolsProtocol.pause_writingc                 C  s   | j  ¡  dS )z_
        Called by the transport when the write buffer drops below the low water mark.
        N)rG   r`   rf   r(   r(   r)   r`   _  s    z HttpToolsProtocol.resume_writingc                 C  s   | j  ¡ s| j  ¡  dS )zk
        Called on a keep-alive connection if no new data is received after a short
        delay.
        N)rF   r®   ra   rf   r(   r(   r)   r±   e  s    
z,HttpToolsProtocol.timeout_keep_alive_handler)N)Ú__name__Ú
__module__Ú__qualname__rQ   rY   rc   rg   rb   rs   ru   rx   ry   r}   r|   r{   r   r‘   r’   r¨   rª   r¬   rŸ   r²   r³   r`   r±   r(   r(   r(   r)   r.   +   s0    û65	r.   c                   @  sj   e Zd Zdddddddddddd	œd
d„Zdddœdd„Zddœdd„Zdddœdd„Zddœdd„ZdS )r   r   rR   r   zlogging.Loggerrt   zlist[tuple[bytes, bytes]]zasyncio.EventzCallable[(Ellipsis, None)]r–   c                 C  sp   || _ || _|| _|| _|| _|| _|| _|| _|| _d| _	|
| _
|	| _d| _d| _d| _d| _d | _d| _d S )NFr   Tr   )rL   rF   rG   r9   r:   r;   r…   r^   r˜   r]   r—   Úwaiting_for_100_continuer©   r«   Úresponse_startedr\   Úchunked_encodingÚexpected_content_length)rP   rL   rF   rG   r9   r:   r;   r…   r^   rN   r—   r˜   r(   r(   r)   rQ   o  s$    zRequestResponseCycle.__init__r	   r/   )r5   r   c              
   Ã  s  zðz|| j| j| jƒI d H }W nV tk
rt } z8d}| jj||d | jsZ|  ¡ I d H  n
| j	 
¡  W 5 d }~X Y nzX |d k	rœd}| j ||¡ | j	 
¡  nR| jsÈ| jsÈd}| j |¡ |  ¡ I d H  n&| jsî| jsîd}| j |¡ | j	 
¡  W 5 dd„ | _ X d S )Nc                   S  s   d S re   r(   r(   r(   r(   r)   Ú<lambda>±  r   z/RequestResponseCycle.run_asgi.<locals>.<lambda>z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.)r˜   rL   ÚreceiveÚsendÚBaseExceptionr9   Úerrorr¸   Úsend_500_responserF   ra   r]   r\   )rP   r5   ÚresultrZ   rw   r(   r(   r)   r¡   —  s2      ÿzRequestResponseCycle.run_asgird   c                 Ã  s:   |   d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)ó   content-lengths   21)ri   ó   close)rŒ   ÚstatusrM   úhttp.response.bodys   Internal Server ErrorF©rŒ   r©   r«   )r¾   rf   r(   r(   r)   rÁ   ³  s    ýýÿ
z&RequestResponseCycle.send_500_responser   )r¦   r   c                 Ã  s,  |d }| j jr&| js&| j  ¡ I d H  | jr0d S | jsø|dkrPd}t|| ƒ‚td|ƒ}d| _d| _|d }| jt	| 
dg ¡ƒ }t| jd kr¤t|kr¤|tg }| jrØ| j d	t| jƒ| jd
 t| jƒ| jd |¡ t| g}|D ]º\}}t |¡rtdƒ‚t |¡rtdƒ‚| ¡ }|dkrJ| jd krJt| ¡ ƒ| _d| _nD|dkrp| ¡ dkrpd| _d| _n|dkrŽ| ¡ dkrŽd| _| |d|dg¡ qæ| jd krØ| jd
 dkrØ|dkrØd| _| d¡ | d¡ | j d  |¡¡ n0| j!s|dkrd}t|| ƒ‚tt"| 
dd¡ƒ}	| 
dd¡}
| jd
 dkrPd| _n‚| jrš|	rrdt#|	ƒ |	dg}ng }|
s†| d¡ | j d  |¡¡ n8t#|	ƒ}|| jkr¸td ƒ‚n|  j|8  _| j |	¡ |
s(| jdkrìtd!ƒ‚d| _!| j$ %¡  | js| j &¡  |  '¡  nd"}t|| ƒ‚d S )#NrŒ   rÃ   z:Expected ASGI message 'http.response.start', but got '%s'.r   TFrÆ   rM   z%s - "%s %s HTTP/%s" %dr~   r   zInvalid HTTP header name.zInvalid HTTP header value.rÄ   s   transfer-encodings   chunkedr   ri   rÅ   r   r!   Z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.)(rG   Zwrite_pausedr]   Zdrainr¸   ÚRuntimeErrorr   r·   r…   ÚlistÚgetr   rL   r;   r:   Úinfor   r   r„   Ú	HEADER_REÚsearchÚHEADER_VALUE_RErj   r¹   r   r™   rº   r—   r†   r   rF   rˆ   r&   r\   r   r‡   r^   r_   ra   r˜   )rP   r¦   Zmessage_typerw   r   rM   r‰   rq   rr   r©   r«   Z	num_bytesr(   r(   r)   r¾   Â  s˜    

ú

&







zRequestResponseCycle.sendr
   c                 Ã  s€   | j r"| j ¡ s"| j d¡ d| _ | jsR| jsR| j ¡  | j 	¡ I d H  | j 
¡  | js^| jrfddiS d| j| jdœ}d| _|S )Ns   HTTP/1.1 100 Continue

FrŒ   zhttp.disconnectzhttp.requestrÈ   r   )r·   rF   r®   rˆ   r]   r\   rG   r¯   r^   ÚwaitÚclearr©   r«   )rP   r¦   r(   r(   r)   r½   ,  s    

zRequestResponseCycle.receiveN)r´   rµ   r¶   rQ   r¡   rÁ   r¾   r½   r(   r(   r(   r)   r   n  s
   "(jr   )2Z
__future__r   r6   r"   r8   Úrer›   Zasyncio.eventsr   Úcollectionsr   Útypingr   r   r   r   r<   Zuvicorn._typesr	   r
   r   r   r   r   Zuvicorn.configr   Zuvicorn.loggingr   Z#uvicorn.protocols.http.flow_controlr   r   r   r   Zuvicorn.protocols.utilsr   r   r   r   r   Zuvicorn.serverr   ÚcompilerÎ   rÐ   r*   Úranger„   ZProtocolr.   r   r(   r(   r(   r)   Ú<module>   s.    

  E