U
    lufl                     @   s  d dl mZ d dlmZm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mZ d dlmZ d dlmZmZ d dlmZmZmZmZ d d	lmZ 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#Z#d dl$Z$d dl%Z%d dl&Z&d dl'm(Z( d dl)Z*d dl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 d dl2m3Z3 d dl+Z+e+j4rPd dl+m5Z5m6Z6m7Z7 G dd deZ8G dd deZ9G dd deZ:G dd dej;Z<e=dkre>e: e	  dS )    )_unicode)genversion)HTTPResponse	HTTPErrorAsyncHTTPClientmain_RequestProxyHTTPRequest)httputil)HTTP1ConnectionHTTP1ConnectionParameters)IOLoop)StreamClosedErrorIOStream)ResolverOverrideResolver_client_ssl_defaultsis_valid_ip)gen_log)	TCPClientN)BytesIO)DictAnyCallableOptionalTypeUnion)TracebackType)DequeTupleListc                       s6   e Zd ZdZedd fddZedddZ  ZS )	HTTPTimeoutErrorzError raised by SimpleAsyncHTTPClient on timeout.

    For historical reasons, this is a subclass of `.HTTPClientError`
    which simulates a response code of 599.

    .. versionadded:: 5.1
    Nmessagereturnc                    s   t  jd|d d S NW  r$   super__init__selfr$   	__class__ =/tmp/pip-unpacked-wheel-bmg6zs32/tornado/simple_httpclient.pyr+   5   s    zHTTPTimeoutError.__init__r%   c                 C   s
   | j pdS )NTimeoutr(   r-   r0   r0   r1   __str__8   s    zHTTPTimeoutError.__str____name__
__module____qualname____doc__strr+   r5   __classcell__r0   r0   r.   r1   r"   ,   s   r"   c                       s6   e Zd ZdZedd fddZedddZ  ZS )	HTTPStreamClosedErroraZ  Error raised by SimpleAsyncHTTPClient when the underlying stream is closed.

    When a more specific exception is available (such as `ConnectionResetError`),
    it may be raised instead of this one.

    For historical reasons, this is a subclass of `.HTTPClientError`
    which simulates a response code of 599.

    .. versionadded:: 5.1
    Nr#   c                    s   t  jd|d d S r&   r)   r,   r.   r0   r1   r+   H   s    zHTTPStreamClosedError.__init__r2   c                 C   s
   | j pdS )NStream closedr(   r4   r0   r0   r1   r5   K   s    zHTTPStreamClosedError.__str__r6   r0   r0   r.   r1   r=   <   s   r=   c                
       s  e Zd ZdZdeeeeef  eee eeee	f  ee ee dd fddZ
dd fd	d
Zeeegdf ddddZddddZedddZeeg df eegdf ddddZeddddZeddddZdeee ddddZ  ZS )SimpleAsyncHTTPClienta  Non-blocking HTTP client with no external dependencies.

    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.
    Some features found in the curl-based AsyncHTTPClient are not yet
    supported.  In particular, proxies are not supported, connections
    are not reused, and callers cannot select the network interface to be
    used.

    This implementation supports the following arguments, which can be passed
    to ``configure()`` to control the global singleton, or to the constructor
    when ``force_instance=True``.

    ``max_clients`` is the number of concurrent requests that can be
    in progress; when this limit is reached additional requests will be
    queued. Note that time spent waiting in this queue still counts
    against the ``request_timeout``.

    ``defaults`` is a dict of parameters that will be used as defaults on all
    `.HTTPRequest` objects submitted to this client.

    ``hostname_mapping`` is a dictionary mapping hostnames to IP addresses.
    It can be used to make local DNS changes when modifying system-wide
    settings like ``/etc/hosts`` is not possible or desirable (e.g. in
    unittests). ``resolver`` is similar, but using the `.Resolver` interface
    instead of a simple mapping.

    ``max_buffer_size`` (default 100MB) is the number of bytes
    that can be read into memory at once. ``max_body_size``
    (defaults to ``max_buffer_size``) is the largest response body
    that the client will accept.  Without a
    ``streaming_callback``, the smaller of these two limits
    applies; with a ``streaming_callback`` only ``max_body_size``
    does.

    .. versionchanged:: 4.2
        Added the ``max_body_size`` argument.
    
   N  @)max_clientshostname_mappingmax_buffer_sizeresolverdefaultsmax_header_sizemax_body_sizer%   c                    s   t  j|d || _t | _i | _i | _|| _|| _	|| _
|rN|| _d| _nt | _d| _|d k	rtt| j|d| _t| jd| _d S )N)rF   FT)rE   mapping)rE   )r*   
initializerB   collectionsdequequeueactivewaitingrD   rG   rH   rE   own_resolverr   r   r   
tcp_client)r-   rB   rC   rD   rE   rF   rG   rH   r.   r0   r1   rJ   v   s,    
 z SimpleAsyncHTTPClient.initializer2   c                    s(   t    | jr| j  | j  d S N)r*   closerP   rE   rQ   r4   r.   r0   r1   rS      s    

zSimpleAsyncHTTPClient.close)requestcallbackr%   c                 C   s   t  }| j|||f |jd k	s&t|jd k	s4td }t| j| jkrt	|j|jp`|jp`|j}|r| j
| j
 | t| j|d}|||f| j|< |   | jrtdt| jt| jf  d S )Nzin request queuezImax_clients limit reached, request queued. %d active, %d queued requests.)objectrM   appendconnect_timeoutAssertionErrorrequest_timeoutlenrN   rB   minio_loopadd_timeouttime	functoolspartial_on_timeoutrO   _process_queuer   debug)r-   rT   rU   keytimeout_handletimeoutr0   r0   r1   
fetch_impl   s0    z SimpleAsyncHTTPClient.fetch_implc                 C   sl   | j rht| j| jk rh| j  \}}}|| jkr2q | | ||f| j|< t| j	|}| 
||| q d S rR   )rM   r[   rN   rB   popleftrO   _remove_timeoutr`   ra   _release_fetch_handle_request)r-   re   rT   rU   release_callbackr0   r0   r1   rc      s    

z$SimpleAsyncHTTPClient._process_queuec                 C   s   t S rR   )_HTTPConnectionr4   r0   r0   r1   _connection_class   s    z'SimpleAsyncHTTPClient._connection_class)rT   rm   final_callbackr%   c              	   C   s&   |   | |||| j| j| j| j d S rR   )ro   rD   rQ   rG   rH   )r-   rT   rm   rp   r0   r0   r1   rl      s    z%SimpleAsyncHTTPClient._handle_request)re   r%   c                 C   s   | j |= |   d S rR   )rN   rc   )r-   re   r0   r0   r1   rk      s    z$SimpleAsyncHTTPClient._release_fetchc                 C   s:   || j kr6| j | \}}}|d k	r.| j| | j |= d S rR   )rO   r]   remove_timeout)r-   re   rT   rU   rf   r0   r0   r1   rj      s
    
z%SimpleAsyncHTTPClient._remove_timeout)re   infor%   c                 C   sn   | j | \}}}| j|||f |r0d|nd}t|dt|| j |j d}| j	|| | j |= dS )zTimeout callback of request.

        Construct a timeout HTTPResponse when a timeout occurs.

        :arg object key: A simple object to mark the request.
        :info string key: More detailed timeout information.
        Timeout {0}r3   r'   )errorrequest_timeN)
rO   rM   removeformatr   r"   r]   r_   
start_timeadd_callback)r-   re   rr   rT   rU   rf   error_messageZtimeout_responser0   r0   r1   rb      s    z!SimpleAsyncHTTPClient._on_timeout)r@   NrA   NNNN)N)r7   r8   r9   r:   intr   r   r;   r   r   rJ   rS   r
   r   r   rh   rc   typero   rl   rV   rk   rj   rb   r<   r0   r0   r.   r1   r?   O   sB   (       & 

r?   c                
   @   sn  e Zd ZedddddddgZee eeg df ee	gdf e
ee
e
dd		d
dZddddZeedeeef ejf dddZd4ee ddddZddddZeedddZeddddZddddZe	ddd d!Zd"ee ee ed#d$d%Z ddd&d'Z!ee"j#e"j$f e"j%dd(d)d*Z&edd+d,Z'ddd-d.Z(ddd/d0Z)e*dd1d2d3Z+dS )5rn   GETHEADPOSTPUTDELETEPATCHOPTIONSN)	clientrT   rm   rp   rD   rQ   rG   rH   r%   c	           	      C   s   t  | _| j | _t | _|| _|| _|| _|| _	|| _
|| _|| _|| _d | _d | _g | _d | _d | _d | _t  t|  dd  d S )Nc                 S   s   |   S rR   resultfr0   r0   r1   <lambda>      z*_HTTPConnection.__init__.<locals>.<lambda>)r   currentr]   r_   rx   start_wall_timer   rT   rm   rp   rD   rQ   rG   rH   codeheaderschunks_decompressor_timeout	_sockaddrZ
add_futurer   Zconvert_yieldedrun)	r-   r   rT   rm   rp   rD   rQ   rG   rH   r0   r0   r1   r+     s*    

 z_HTTPConnection.__init__r2   c                    s:  z
t jt| jj| _| jjdkr6td| jj | jj	}d|krV|
d\}}}t|\}}|d kr| jjdkr|dnd}td|r|dd	 }|| _| jjd
krtj}ntj}| | jj}d }| jjrt| jjr| jj}ntd| jjf | jjr"| jjr"t| jj| jj}	n,| jjr6| jj}	n| jjrJ| jj}	nd}	|	rt| j| j|	 t| jd| _ | j!j"||||| j#|dI d H }
| j$d kr|
%  W d S |
| _&| j&'| j( | )  | j$d krW d S | jjr
| j| j| jj t| jd| _ | jj*| j+kr4| jj,s4t-d| jj* dD ]"}t.| j|d r8t/d| q8d| jj0krvd| jj0d< d| jj0krd| jj	kr| jj	
dd	 | jj0d< n| jj	| jj0d< d\}}| jj1d k	r| jj1| jj2 }}n$| jj3d k	r| jj3}| jj4p
d}|d k	rb|d k	s$t5| jj6dkr@td| jj6dtt78t9|| | jj0d< | jj:r~| jj:| jj0d< n&| jj0;dd krd<t=| jj0d< | jj,s
| jj*dk}| jj>d k	p| jj?d k	}|r|r|r
|s
td|rd nd| jj*f | jj@r d!| jj0d"< | jj>d k	rFtAtB| jj>| jj0d#< | jj*d$krnd%| jj0krnd&| jj0d%< | jjCrd'| jj0d(< | jjDpd)| jjErd*| jjE nd }| F|
| _GtH| jj*|d}| jGI|| jj0 | jj@r| jGJ| I d H  n| Kd+I d H  W n( tLk
r4   | jMtNO  s0 Y nX d S ),N)httphttpszUnsupported url scheme: %s@r   i  P   z^\[.*\]$   Fz?Unrecognized IPv4 or IPv6 address for network_interface, got %rr   zwhile connecting)afssl_optionsrD   	source_ipzduring requestzunknown method %s)Z
proxy_hostZ
proxy_portZproxy_usernameZproxy_passwordZproxy_auth_modez%s not supported
ConnectionrS   Host)NN )Nbasiczunsupported auth_mode %szBasic Authorizationz
User-Agentz
Tornado/{})r   r   r   zLBody must %sbe None for method %s (unless allow_nonstandard_methods is true)znot z100-continueZExpectContent-Lengthr   Content-Typez!application/x-www-form-urlencodedgzipzAccept-Encoding/?T)Purllibparseurlsplitr   rT   urlparsedscheme
ValueErrornetloc
rpartitionr   Zsplit_host_and_portrematchZparsed_hostnameZ
allow_ipv6socketAF_INET	AF_UNSPEC_get_ssl_optionsZnetwork_interfacer   rX   rZ   r\   r]   r^   rx   r`   ra   rb   r   rQ   connectrD   rp   rS   streamZset_close_callbackon_connection_closerj   method_SUPPORTED_METHODSZallow_nonstandard_methodsKeyErrorgetattrNotImplementedErrorr   usernamepasswordZauth_usernameZauth_passwordrY   Z	auth_modebase64	b64encodeZencode_username_password
user_agentgetrw   r   bodybody_producerexpect_100_continuer;   r[   decompress_responsepathquery_create_connection
connectionRequestStartLineZwrite_headersread_response_write_body	Exception_handle_exceptionsysexc_info)r-   r   Zuserpass_hostportr   r   r   rg   r   re   r   r   Zbody_expectedZbody_presentreq_pathZ
start_liner0   r0   r1   r   "  s   
 



	










z_HTTPConnection.run)r   r%   c                 C   s   |dkr| j jd k	r| j jS | j jrL| j jd krL| j jd krL| j jd krLtS tjtj	j
| j jd}| j jsxd|_tj|_| j jd k	r|| j j| j j ttdr| jtjO  _|S d S )Nr   )cafileFOP_NO_COMPRESSION)rT   r   Zvalidate_certca_certsclient_certZ
client_keyr   sslcreate_default_contextPurposeSERVER_AUTHcheck_hostname	CERT_NONEverify_modeload_cert_chainhasattroptionsr   )r-   r   Zssl_ctxr0   r0   r1   r     s8    


  
z _HTTPConnection._get_ssl_options)rr   r%   c                 C   s8   d| _ |rd|nd}| jdk	r4| tt|d dS )zTimeout callback of _HTTPConnection instance.

        Raise a `HTTPTimeoutError` when a timeout occurs.

        :info string key: More detailed timeout information.
        Nrs   r3   )r   rw   rp   r   r"   )r-   rr   rz   r0   r0   r1   rb     s    
  z_HTTPConnection._on_timeoutc                 C   s"   | j d k	r| j| j  d | _ d S rR   )r   r]   rq   r4   r0   r0   r1   rj     s    
z_HTTPConnection._remove_timeout)r   r%   c              	   C   s6   | d t|dtd| j| jt| jjd| j}|S )NT)Zno_keep_aliverG   rH   
decompress)	Zset_nodelayr   r   rG   rH   boolrT   r   r   )r-   r   r   r0   r0   r1   r     s    

z"_HTTPConnection._create_connection)
start_readr%   c                    s   | j jd k	r| j| j j n.| j jd k	rL| j | jj}|d k	rL|I d H  | j  |rz| j| I d H  W n$ tk
r   | jt	
  s Y nX d S rR   )rT   r   r   writer   finishr   r   r   r   r   )r-   r   futr0   r0   r1   r     s    

z_HTTPConnection._write_bodyc                 C   s    | j d k	r| j }d | _ |  d S rR   )rm   )r-   rm   r0   r0   r1   _release  s    
z_HTTPConnection._release)responser%   c                 C   s0   |    | jd k	r,| j}d | _| j|| d S rR   )r   rp   r]   ry   )r-   r   rp   r0   r0   r1   _run_callback  s
    
z_HTTPConnection._run_callbackzOptional[Type[BaseException]])typvaluetbr%   c              	   C   s   | j d k	rv|   t|tr6|jd kr0td}n|j}| t| jd|| j	
 | j | jd t| drr| j  dS t|tS d S )Nr>   r'   )rt   ru   rx   r   T)rp   rj   
isinstancer   Z
real_errorr=   r   r   rT   r]   r_   rx   r   r   r   rS   )r-   r   r   r   r0   r0   r1   r      s&    






z!_HTTPConnection._handle_exceptionc                 C   sR   | j d k	rNd}| jjr| jjzt|W n" tk
rL   | jt   Y nX d S )NzConnection closed)rp   r   rt   r=   r   r   r   r,   r0   r0   r1   r   D  s    
z#_HTTPConnection.on_connection_close)
first_liner   r%   c                    s   t |tjst| jjr6|jdkr6| dI d H  d S |j| _|j| _|| _	| 
 rXd S | jjd k	r| jd|  | j	 D ]\}}| jd||f  q~| jd d S )Nd   Fz
%s %s %s
z%s: %s
z
)r   r   ResponseStartLinerY   rT   r   r   r   reasonr   _should_follow_redirectZheader_callbackget_all)r-   r   r   kvr0   r0   r1   headers_receivedN  s    z _HTTPConnection.headers_receivedc                 C   sL   | j jrH| j jd k	st| jdkoF| j jdkoF| jd k	oF| jdd k	S dS )N)-  .  /  i3  i4  r   LocationF)rT   Zfollow_redirectsmax_redirectsrY   r   r   r   r4   r0   r0   r1   r   e  s    

z'_HTTPConnection._should_follow_redirectc              
      s  | j d k	std| j}|   t| jd| j}|  rlt| jt	sLt| j
d k	sZtt| jj}tj| jj| j
d |_| jjd k	st| jjd |_|j
d= | j dkr| jjdks| j dkr| jjd	krd
|_d |_dD ]*}z| jj
|= W q tk
r   Y qX q||_| j d | _|   | jd k	s>t| jj|dd}| fdd |   d S | jjr~t }nt|}t|| j t| dd | j
| j | j  | j!|| jjd}| "| |   d S )Nr   original_requestr   r   r   r   r~   )r   r   r   r}   )r   r   zContent-EncodingzTransfer-EncodingF)Zraise_errorc                    s    |   S rR   r   r   rp   r0   r1   r     r   z(_HTTPConnection.finish.<locals>.<lambda>r   )r   r   ru   rx   bufferZeffective_url)#r   rY   joinr   rj   r   rT   r   r   r	   r   copyr   r   urljoinr   r   r   r   r   r   rp   r   r   fetchZadd_done_callback_on_end_requeststreaming_callbackr   r   r]   r_   rx   r   r   )r-   datar   Znew_requesthr   r  r   r0   r  r1   r   p  sf    
 





z_HTTPConnection.finishc                 C   s   | j   d S rR   )r   rS   r4   r0   r0   r1   r    s    z_HTTPConnection._on_end_request)chunkr%   c                 C   s6   |   rd S | jjd k	r&| j| n| j| d S rR   )r   rT   r  r   rW   )r-   r  r0   r0   r1   data_received  s
    z_HTTPConnection.data_received)N),r7   r8   r9   setr   r   r?   r
   r   r   r{   r   r+   r   r;   r   r   r   r   
SSLContextr   rb   rj   r   r   r   r   r   r   r   BaseExceptionr   r   r   r   r   r   ZHTTPHeadersr   r   r   r  bytesr  r0   r0   r0   r1   rn      sL   
! #	$Arn   __main__)?Ztornado.escaper   Ztornador   r   Ztornado.httpclientr   r   r   r   r	   r
   r   Ztornado.http1connectionr   r   Ztornado.ioloopr   Ztornado.iostreamr   r   Ztornado.netutilr   r   r   r   Ztornado.logr   Ztornado.tcpclientr   r   rK   r  r`   r   r   r   r   r_   ior   urllib.parser   typingr   r   r   r   r   r   typesr   TYPE_CHECKINGr   r    r!   r"   r=   r?   ZHTTPMessageDelegatern   r7   	configurer0   r0   r0   r1   <module>   sH      .   E

