U
    u?dW                     @   s  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
 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mZmZmZ d dlZd dlZdd	l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'm(Z( ddl)m*Z*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8m9Z9 dZ:erZddl;m<Z< ee'e.dedge6f Z=ee6gee9 f Z>e'dde&i i dddde?d
Z@G dd deAZBG dd deAZCejDdddd G d!d" d"ZEeee'eEf e.f ZFG d#d de!ZGdS )$    N)deque)suppress)escape)
HTTPStatus)Logger)TYPE_CHECKINGAny	AwaitableCallableDequeOptionalSequenceTupleTypeUnioncast   )AbstractAccessLoggerAbstractStreamWriter)BaseProtocol)ceil_timeout)HttpProcessingErrorHttpRequestParserHttpVersion10RawRequestMessageStreamWriter)access_loggerserver_logger)EMPTY_PAYLOADStreamReader)tcp_keepalive)HTTPException)AccessLogger)BaseRequest)ResponseStreamResponse)RequestHandlerRequestPayloadErrorPayloadAccessError)Serverr&   zasyncio.Task[None]UNKNOWN/TFc                   @   s   e Zd ZdZdS )r'   zPayload parsing error.N__name__
__module____qualname____doc__ r1   r1   8/tmp/pip-unpacked-wheel-_pk67_um/aiohttp/web_protocol.pyr'   N   s   r'   c                   @   s   e Zd ZdZdS )r(   z-Payload was accessed after response was sent.Nr,   r1   r1   r1   r2   r(   R   s   r(   )Zauto_attribsfrozenslotsc                   @   s&   e Zd ZU eed< eed< eed< dS )_ErrInfostatusexcmessageN)r-   r.   r/   int__annotations__BaseExceptionstrr1   r1   r1   r2   r5   V   s   
r5   c                       s  e Zd ZdZdZdZddeeeej	ddddd	d
ddde
jeeeee eeeeeeeeed fddZedddZeedddZdHee ddddZe
jdd fddZee dd fddZedd d!d"Zddd#d$Ze dd%d&d'Z!edd(d)d*Z"ddd+d,Z#ddd-d.Z$e%e&edd/d0d1Z'eedd2d3d4Z(eedd2d5d6Z)ddd7d8Z*e%ee+e%ge,e& f e-e&ef d9d:d;Z.ddd<d=Z/e%e&eed>d?d@Z0dIe%eee ee e&dBdCdDZ1e2e+e%ge,e& f dEdFdGZ3  Z4S )Jr&   a  HTTP protocol implementation.

    RequestHandler handles incoming HTTP request. It reads request line,
    request headers and request payload and calls handle_request() method.
    By default it always returns with 404 response.

    RequestHandler handles errors in incoming request, like bad
    status line, bad headers or incomplete payload. If any error occurs,
    connection gets closed.

    keepalive_timeout -- number of seconds before closing
                         keep-alive connection

    tcp_keepalive -- TCP keep-alive is on, default is on

    debug -- enable debug mode

    logger -- custom logger object

    access_log_class -- custom class for access_logger

    access_log -- custom logging object

    access_log_format -- access log format string

    loop -- Optional event loop

    max_line_size -- Optional maximum header line size

    max_field_size -- Optional maximum header field size

    max_headers -- Optional maximum header size

    r   )_request_count
_keepalive_manager_request_handler_request_factory_tcp_keepalive_keepalive_time_keepalive_handle_keepalive_timeout_lingering_time	_messages_message_tail_waiter_task_handler_upgrade_payload_parser_request_parserZ_reading_pausedloggerdebug
access_logr   _close_force_close_current_requestg     R@TFi  i   g      $@i   )keepalive_timeoutr    rN   access_log_classrP   access_log_formatrO   max_line_sizemax_headersmax_field_sizelingering_timeread_bufsizeauto_decompressr)   )managerlooprT   r    rN   rU   rP   rV   rO   rW   rX   rY   rZ   r[   r\   c             
      s   t  | d| _d| _d | _|| _|j| _|j| _	|| _
d| _d | _|| _t|| _t | _d| _d | _d | _d| _d | _t| |||
||t|d| _|| _|	| _|| _|r|||| _nd | _d| _d| _d S )Nr   Fg            )rW   rY   rX   Zpayload_exceptionr\   ) super__init__r=   r>   rS   r?   request_handlerr@   Zrequest_factoryrA   rB   rC   rD   rE   floatrF   r   rG   rH   rI   rJ   rK   rL   r   r'   rM   rN   rO   rP   r   rQ   rR   )selfr]   r^   rT   r    rN   rU   rP   rV   rO   rW   rX   rY   rZ   r[   r\   	__class__r1   r2   ra      sN    
 zRequestHandler.__init__)returnc                 C   s   d | jj| jd k	rdndS )Nz<{} {}>	connectedZdisconnected)formatrf   r-   	transportrd   r1   r1   r2   __repr__   s    zRequestHandler.__repr__c                 C   s   | j S N)rE   rk   r1   r1   r2   rT      s    z RequestHandler.keepalive_timeout      .@N)timeoutrg   c                    s   d| _ | jdk	r| j  | jr*| j  ttjtjb t|4 I dH @ | j	dk	rf| j	
t  | jdk	r| j s| jI dH  W 5 Q I dH R X W 5 Q R X | jdk	r| j  | jdk	r| j  d| _dS )zDo worker process exit preparations.

        We need to clean up everything and stop accepting requests.
        It is especially important for keep-alive connections.
        TN)rR   rD   cancelrI   r   asyncioCancelledErrorTimeoutErrorr   rS   _cancelrJ   donerj   close)rd   ro   r1   r1   r2   shutdown   s     



&



zRequestHandler.shutdown)rj   rg   c                    sX   t  | ttj|}| jr&t| | j| 	 | _
| jd k	sFt| j| | d S rm   )r`   connection_mader   rq   	TransportrB   r    _loopcreate_taskstartrJ   r?   AssertionError)rd   rj   Zreal_transportre   r1   r2   rx     s    zRequestHandler.connection_made)r7   rg   c                    s   | j d krd S | j | | t | d | _ d| _d | _d | _d | _| jd k	rZ| j  | j	d k	r|d krtt
d}| j	| | jd k	r| j  d | _| jd k	r| j  d | _d S )NTzConnection lost)r?   connection_lostr`   rR   rA   r@   rM   rD   rp   rS   ConnectionResetErrorrt   rI   rJ   rL   Zfeed_eof)rd   r7   re   r1   r2   r~     s*    







zRequestHandler.connection_lost)parserrg   c                 C   s2   | j d kst|| _ | jr.| j | j d| _d S )Nr_   )rL   r}   rH   	feed_data)rd   r   r1   r1   r2   
set_parser7  s
    zRequestHandler.set_parserc                 C   s   d S rm   r1   rk   r1   r1   r2   eof_receivedA  s    zRequestHandler.eof_received)datarg   c           
   
   C   sB  | j s| jrd S | jd kr| js| jd k	s.tz| j|\}}}W n@ tk
r } z"td||j	dt
fg}d}d}W 5 d }~X Y nX |pdD ]&\}}|  jd7  _| j||f q| j}|r|d k	r| s|d  || _|r|r|| _nN| jd kr| jr|r|  j|7  _n$|r>| j|\}	}|	r>|   d S )Ni  )r6   r7   r8   Fr_   r1   r   )rR   rQ   rL   rK   rM   r}   r   r   r5   r8   r   r=   rG   appendrI   ru   Z
set_resultrH   rv   )
rd   r   messagesZupgradedtailr7   msgpayloadwaitereofr1   r1   r2   data_receivedD  s4    
zRequestHandler.data_received)valrg   c                 C   s    || _ | jr| j  d| _dS )zMSet keep-alive connection mode.

        :param bool val: new state.
        N)r>   rD   rp   )rd   r   r1   r1   r2   
keep_alivek  s    
zRequestHandler.keep_alivec                 C   s   d| _ | jr| j  dS )zClose connection.

        Stop accepting new pipelining messages and close
        connection when handlers done processing messages.
        TN)rQ   rI   rp   rk   r1   r1   r2   rv   u  s    zRequestHandler.closec                 C   s4   d| _ | jr| j  | jdk	r0| j  d| _dS )zForcefully close connection.TN)rR   rI   rp   rj   rv   rk   r1   r1   r2   force_close  s    


zRequestHandler.force_close)requestresponsetimerg   c                 C   s(   | j d k	r$| j ||| j |  d S rm   )r   logrz   r   )rd   r   r   r   r1   r1   r2   
log_access  s    
zRequestHandler.log_access)argskwrg   c                 O   s   | j r| jj || d S rm   )rO   rN   rd   r   r   r1   r1   r2   	log_debug  s    zRequestHandler.log_debugc                 O   s   | j j|| d S rm   )rN   	exceptionr   r1   r1   r2   log_exception  s    zRequestHandler.log_exceptionc                 C   sT   | j s| jsd S | j| j }| jr<| j |kr<|   d S | j| j	| j
| _d S rm   )rR   r>   rC   rE   rI   rz   r   r   Z
call_laterKEEPALIVE_RESCHEDULE_DELAY_process_keepaliverD   )rd   nextr1   r1   r2   r     s     z!RequestHandler._process_keepalive)r   
start_timerb   rg   c              
      sP  | j d k	stz&z|| _||I d H }W 5 d | _X W n tk
rn } z|}| |||I d H }W 5 d }~X Y n tjk
r    Y n tjk
r } z2| jd|d | 	|d}| |||I d H }W 5 d }~X Y nt t
k
r } z&| 	|d|}| |||I d H }W 5 d }~X Y n0X t|ddr4tdt | |||I d H }||fS )NzRequest handler timed out.exc_infoi    Z__http_exception__Fzlreturning HTTPException object is deprecated (#2415) and will be removed, please raise the exception instead)r@   r}   rS   r!   finish_responserq   rr   rs   r   handle_error	ExceptiongetattrwarningswarnDeprecationWarning)rd   r   r   rb   respr7   resetr1   r1   r2   _handle_request  s2    $$&zRequestHandler._handle_requestc                    s  | j }| j}|dk	st| j}|dk	s*t| j}d}| jdk	sBt| jdk	sPt| js| jsz@z|
 | _	| j	I dH  W n  tjk
r   Y W qY nX W 5 d| _	X | j \}}| }| jd7  _t| |}	t|tr| |}
t}n| j}
| ||| |	|}dzzh| j | |||
}z|I dH \}}W n6 tjtfk
rp   | d Y W W  qY nX ~|r| d W W  qt |j!| _|" sj| j#}| jsF|rF| d| | }|| }t$tj%tjZ |" s<||k r<t&|| 4 I dH  |' I dH  W 5 Q I dH R X | }qW 5 Q R X |" sj| jsj| d | (  |)t*  W n tjk
r   | d Y W  qY nz t+k
r } z"| j,r| j-d	|d
 | .  W 5 d}~X Y n: t/k
r } z| j-d|d
 | .  W 5 d}~X Y nX W 5 | jdkrF|dk	rF| d n\| js| jr| js|dk	r| j  }|| _| jdkr||| | j| _n  qX  qP| jsd| _| jdk	r| j(  dS )a_  Process incoming request.

        It reads request line, request headers and request payload, then
        calls handle_request() method. Subclass has to override
        handle_request(). start() handles various exceptions in request
        or response handling. Connection is being closed always unless
        keep_alive(True) specified.
        Nr   z'Ignored premature client disconnection.z&Ignored premature client disconnectionz(Ignored premature client disconnection 2z'Start lingering close timer for %s sec.zUncompleted request.z'Ignored premature client disconnection zUnhandled runtime exceptionr   zUnhandled exception)0rz   rJ   r}   r?   rE   rA   r@   rR   rG   rI   Zcreate_futurerq   rr   popleftr   Zrequests_countr   
isinstancer5   _make_error_handlerERRORrj   r   r>   rQ   rC   rD   Zcall_atr   r{   r   ConnectionErrorboolr   Zis_eofrF   r   rs   r   Zreadanyrv   Zset_exceptionr(   RuntimeErrorrO   r   r   r   )rd   r^   handlerr]   rT   r   r8   r   r|   writerrb   r   nowZtaskr   rZ   Zend_tr7   r1   r1   r2   r|     s    	







 



 zRequestHandler.start)r   r   r   rg   c                    s   | j dk	r6| j d d| _| jr6| j | j d| _z
|j}W n4 tk
rt   |dkrbtdntd|Y nX z ||I dH  |	 I dH  W n$ t
k
r   | ||| Y dS X | ||| dS dS )a   Prepare the response and write_eof, then log access.

        This has to
        be called within the context of any exception so the access logger
        can get exception information. Returns True if the client disconnects
        prematurely.
        NFr_   z+Missing return statement on request handlerz7Web-handler should return a response instance, got {!r}T)rM   Zset_upgradedrK   rH   r   prepareAttributeErrorr   ri   	write_eofr   r   )rd   r   r   r   Zprepare_methr1   r1   r2   r   G  s0    




zRequestHandler.finish_responser   )r   r6   r7   r8   rg   c           
   	   C   s   | j d|d |jjdkr"tdd}|tjkrdtj}tjj}d}| jrjt	t
 t }W 5 Q R X d|jd	d
kr|rt|}d| d}dj||d}d}n|r|}|d | }t|||d}	|	  |	S )zHandle errors.

        Returns HTTP response with specific status code. Logs additional
        information. It always closes current connection.
        zError handling requestr   r   zMResponse is sent already, cannot send another response with the error messagez
text/plainz{0.value} {0.phrase}Nz	text/htmlAccept z<h2>Traceback:</h2>
<pre>z</pre>zV<html><head><title>{title}</title></head><body>
<h1>{title}</h1>
{msg}
</body></html>
)titler   z

)r6   textcontent_type)r   r   Zoutput_sizer   r   INTERNAL_SERVER_ERRORri   descriptionrO   r   r   	traceback
format_excheadersgethtml_escaper$   r   )
rd   r   r6   r7   r8   ctr   r   tbr   r1   r1   r2   r   l  s:    

 zRequestHandler.handle_error)err_inforg   c                    s   t td fdd}|S )N)r   rg   c                    s    |  j j jS rm   )r   r6   r7   r8   )r   r   rd   r1   r2   r     s       z3RequestHandler._make_error_handler.<locals>.handler)r#   r%   )rd   r   r   r1   r   r2   r     s    z"RequestHandler._make_error_handler)rn   )r   NN)5r-   r.   r/   r0   r   	__slots__r   r"   r   Z
LOG_FORMATrq   ZAbstractEventLooprc   r   r   r   r   r<   r9   ra   rl   propertyrT   r   rw   ZBaseTransportrx   r;   r~   r   r   r   bytesr   r   rv   r   r#   r%   r   r   r   r   r
   r	   r   r   r|   r   r   r5   r   __classcell__r1   r1   re   r2   r&   `   s   #!C
'


  
'z  (   4)Hrq   Zasyncio.streamsr   r   collectionsr   
contextlibr   htmlr   r   httpr   loggingr   typingr   r   r	   r
   r   r   r   r   r   r   r   attrZyarlabcr   r   Zbase_protocolr   Zhelpersr   r   r   r   r   r   r   r   r   Zstreamsr   r   Ztcp_helpersr    Zweb_exceptionsr!   Zweb_logr"   Zweb_requestr#   Zweb_responser$   r%   __all__Z
web_serverr)   Z_RequestFactoryZ_RequestHandlerURLr   r   r'   r(   sr5   Z_MsgTyper&   r1   r1   r1   r2   <module>   sl   4