U
    j7g$a                     @   s  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 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l0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z:m;Z; dZ<erfddl=m>Z> ee(e/de dge8f Z?ee8gee; f Z@e(dde'i i ddddeAd
ZBG dd deCZDG dd deCZEeE ZFejGdddd G d!d" d"ZHeee(eHf e/f ZIG d#d de"ZJd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HTTPInternalServerError)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__ r2   r2   8/tmp/pip-unpacked-wheel-cme3dcq2/aiohttp/web_protocol.pyr(   O   s   r(   c                   @   s   e Zd ZdZdS )r)   z-Payload was accessed after response was sent.Nr-   r2   r2   r2   r3   r)   S   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/   r0   int__annotations__BaseExceptionstrr2   r2   r2   r3   r6   Z   s   
r6   c                       s  e Zd ZdZdZddeeeejd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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,e%ef d>d?d@Z/dIe$eee ee e%dBdCdDZ0e1e*e$ge+e% f dEdFdGZ2  Z3S )Jr'   aj  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

    timeout_ceil_threshold -- Optional value to specify
                              threshold to ceil() timeout
                              values

    )_request_count
_keepalive_manager_request_handler_request_factory_tcp_keepalive_next_keepalive_close_time_keepalive_handle_keepalive_timeout_lingering_time	_messages_message_tail_handler_waiter_waiter_task_handler_upgrade_payload_parser_request_parserZ_reading_pausedloggerdebug
access_logr   _close_force_close_current_request_timeout_ceil_threshold_request_in_progressg     R@TFi  i   g      $@i      )keepalive_timeoutr    rP   access_log_classrR   access_log_formatrQ   max_line_sizemax_headersmax_field_sizelingering_timeread_bufsizeauto_decompresstimeout_ceil_thresholdr*   )managerlooprY   r    rP   rZ   rR   r[   rQ   r\   r]   r^   r_   r`   ra   rb   c             
      s
  t  | d| _d| _d | _|| _|j| _|j| _	|| _
d| _d | _|| _t|| _t | _d| _d | _d | _d | _d| _d | _t| |||
||t|d| _d| _zt|| _W n ttfk
r   Y nX || _|	| _|| _ |r|||| _!nd | _!d| _"d| _#d| _$d S )Nr   Fg            )r\   r^   r]   Zpayload_exceptionra   rX   )%super__init__r>   r?   rU   r@   request_handlerrA   Zrequest_factoryrB   rC   rD   rE   rF   floatrG   r   rH   rI   rK   rJ   rL   rM   rN   r   r(   rO   rV   	TypeError
ValueErrorrP   rQ   rR   r   rS   rT   rW   )selfrc   rd   rY   r    rP   rZ   rR   r[   rQ   r\   r]   r^   r_   r`   ra   rb   	__class__r2   r3   rg      s\    
 zRequestHandler.__init__)returnc                 C   s   d | jj| jd k	rdndS )Nz<{} {}>	connectedZdisconnected)formatrn   r.   	transportrl   r2   r2   r3   __repr__   s    zRequestHandler.__repr__c                 C   s   | j S N)rF   rs   r2   r2   r3   rY      s    z RequestHandler.keepalive_timeout      .@N)timeoutro   c              
      sp  d| _ | jdk	r| j  | jr| j | _z2t|4 I dH  | jI dH  W 5 Q I dH R X W nB tj	tj
fk
r   d| _tjdkrt  }r| r Y nX zft|4 I dH F | jdk	r| jt	  | jdk	r| j st| jI dH  W 5 Q I dH R X W nD tj	tj
fk
rL   tjdkrHt  }rH| rH Y nX | jdk	rd| j  |   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      )rT   rE   cancelrW   _loopcreate_futurerJ   r   asyncioCancelledErrorTimeoutErrorsysversion_infocurrent_task
cancellingrU   _cancelrL   doneZshieldforce_close)rl   rw   taskr2   r2   r3   shutdown  sD    

 

&

zRequestHandler.shutdown)rr   ro   c                    s   t  | ttj|}| jr&t| | jd k	s4t| j| | | j	}t
jdkrhtj|  |dd}n||  }|| _d S )Nry      Trd   Zeager_start)rf   connection_mader   r~   	TransportrC   r    r@   AssertionErrorr|   r   r   Taskstartcreate_taskrL   )rl   rr   Zreal_transportrd   r   rm   r2   r3   r   3  s    
zRequestHandler.connection_made)r8   ro   c                    s   | j d krd S | j | | | j j}|   t | d | _ d | _d | _d | _| jd k	rd| j	  | j
d k	r|d kr~td}| j
| |r| jd k	r| j	  d | _| jd k	r| j  d | _d S )NzConnection lost)r@   connection_losthandler_cancellationr   rf   rB   rA   rO   rE   r{   rU   ConnectionResetErrorr   rL   rN   Zfeed_eof)rl   r8   r   rm   r2   r3   r   D  s,    






zRequestHandler.connection_lost)parserro   c                 C   s2   | j d kst|| _ | jr.| j | j d| _d S )Nre   )rN   r   rI   	feed_data)rl   r   r2   r2   r3   
set_parserd  s
    zRequestHandler.set_parserc                 C   s   d S ru   r2   rs   r2   r2   r3   eof_receivedn  s    zRequestHandler.eof_received)dataro   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  )r7   r8   r9   Fre   r2   r   )rT   rS   rN   rM   rO   r   r   r   r6   r9   r   r>   rH   appendrK   r   
set_resultrI   close)
rl   r   messagesZupgradedtailr8   msgpayloadwaitereofr2   r2   r3   data_receivedq  s4    
zRequestHandler.data_received)valro   c                 C   s    || _ | jr| j  d| _dS )zMSet keep-alive connection mode.

        :param bool val: new state.
        N)r?   rE   r{   )rl   r   r2   r2   r3   
keep_alive  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)rS   rK   r{   rs   r2   r2   r3   r     s    zRequestHandler.closec                 C   s4   d| _ | jr| j  | jdk	r0| j  d| _dS )zForcefully close connection.TN)rT   rK   r{   rr   r   rs   r2   r2   r3   r     s    


zRequestHandler.force_close)requestresponsetimero   c                 C   s(   | j d k	r$| j ||| j |  d S ru   )r   logr|   r   )rl   r   r   r   r2   r2   r3   
log_access  s    
zRequestHandler.log_access)argskwro   c                 O   s   | j r| jj || d S ru   )rQ   rP   rl   r   r   r2   r2   r3   	log_debug  s    zRequestHandler.log_debugc                 O   s   | j j|| d S ru   )rP   	exceptionr   r2   r2   r3   log_exception  s    zRequestHandler.log_exceptionc                 C   sb   d | _ | js| jsd S | j}| }| j}||krF||| j| _ d S | jr^| j	 s^| 
  d S ru   )rE   rT   r?   r|   r   rD   call_at_process_keepaliverK   r   r   )rl   rd   now
close_timer2   r2   r3   r     s    z!RequestHandler._process_keepalive)r   
start_timerh   ro   c              
      s  d| _ zNz&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 } z6| j	d|d | 
|d}| |||I d H \}}W 5 d }~X Y n| tk
r  } z*| 
|d|}| |||I d H \}}W 5 d }~X Y n4X t|ddr<tdt | |||I d H \}}W 5 d| _ | jd k	rv| jd  X ||fS )	NTFzRequest handler timed out.exc_infoi    Z__http_exception__zlreturning HTTPException object is deprecated (#2415) and will be removed, please raise the exception instead)rW   rJ   r   rU   r!   finish_responser~   r   r   r   handle_error	ExceptiongetattrwarningswarnDeprecationWarning)rl   r   r   rh   respr8   resetr2   r2   r3   _handle_request  s8    ((*zRequestHandler._handle_requestc                    s  | j }t|}|dk	st| j}|dk	s.t| j}d}| jdk	sFt| jdk	sTt| js| j	sz| | _
| j
I dH  W 5 d| _
X | j	 \}}| }| jd7  _t| |}	t|tr| |}
t}n| j}
| ||| |	|}dzz| |||
}tjdkrtj||dd}n
| |}z|I dH \}}W n0 t!k
rh   | d Y W W  qY nX ~|r| d W W | qt"|j#| _|$ s| j%}| jsn|rn| d	| | }|| }zX|$ s&||k r&t&|| 4 I dH  |' I dH  W 5 Q I dH R X | }qW nD tj(tj)fk
rl   tjd
krht  }rh|* rh Y nX |$ s| js| d | +  |,t- W n\ tj(k
r   | d  Y n: t.k
r } z| j/d|d | 0  W 5 d}~X Y nX W 5 | jdkr"|dk	r"| d n^| js| jrx| jsx|dk	r| }|| }|| _| jdkr||| j| _n  qX  qT| jsd| _1| 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.r   Tr   z&Ignored premature client disconnectionz(Ignored premature client disconnection 2z'Start lingering close timer for %s sec.rx   zUncompleted request.zUnhandled exceptionr   )2r|   r~   r   r   r@   rF   rB   rA   rT   rH   rK   r}   popleftr   Zrequests_countr   
isinstancer6   _make_error_handlerERRORrr   r   r?   rS   rD   rE   r   r   r   r   r   r   r   ConnectionErrorboolr   Zis_eofrG   r   Zreadanyr   r   r   r   Zset_exception_PAYLOAD_ACCESS_ERRORr   r   r   rL   )rl   rd   handlerrc   rY   r   r9   r   r   writerrh   r   r   r   coror   r   r_   Zend_ttr8   r2   r2   r3   r     s    	









 



 zRequestHandler.start)r   r   r   ro   c              	      s  |   | jdk	r>| jd d| _| jr>| j| j d| _z
|j}W n\ tk
r   |dkrl| d n| d	| t
 }t|j|j|j|jd}|j}Y nX z ||I dH  | I dH  W n* tk
r   | ||| |df Y S X | ||| |df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.
        NFre   z+Missing return statement on request handlerz7Web-handler should return a response instance, got {!r})r7   reasontextheadersT)Z_finishrO   Zset_upgradedrM   rI   r   prepareAttributeErrorr   rq   r"   r%   r7   r   r   r   	write_eofr   r   )rl   r   r   r   Zprepare_methr8   r2   r2   r3   r   {  sB    


   zRequestHandler.finish_responser   )r   r7   r8   r9   ro   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

)r7   r   content_type)r   r   Zoutput_sizer   r   INTERNAL_SERVER_ERRORrq   descriptionrQ   r   r   	traceback
format_excr   gethtml_escaper%   r   )
rl   r   r7   r8   r9   ctr   r   tbr   r2   r2   r3   r     s:    

 zRequestHandler.handle_error)err_inforo   c                    s   t td fdd}|S )N)r   ro   c                    s    |  j j jS ru   )r   r7   r8   r9   )r   r   rl   r2   r3   r     s       z3RequestHandler._make_error_handler.<locals>.handler)r$   r&   )rl   r   r   r2   r   r3   r     s    z"RequestHandler._make_error_handler)rv   )r   NN)4r.   r/   r0   r1   	__slots__r   r#   r   Z
LOG_FORMATr~   ZAbstractEventLoopri   r   r   r   r   r=   r:   rg   rt   propertyrY   r   r   ZBaseTransportr   r<   r   r   r   r   bytesr   r   r   r   r$   r&   r   r   r   r   r
   r	   r   r   r   r   r   r6   r   __classcell__r2   r2   rm   r3   r'   d   s   '$L2 
'


  
+~  
-   4)Kr~   Zasyncio.streamsr   r   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!   r"   Zweb_logr#   Zweb_requestr$   Zweb_responser%   r&   __all__Z
web_serverr*   Z_RequestFactoryZ_RequestHandlerURLr   r   r(   r)   r   sr6   Z_MsgTyper'   r2   r2   r2   r3   <module>   sp   4