U
    .e&                     @  s   d 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 ddlmZ dd	lmZ d
dlmZ zddlZW n  ek
r   d Z ZZY n$X ddlmZ ejejejejdZdZdZedddgZ G dd deZ!dS )zHTTP Client using pyCurl.    )annotations)deque)partial)BytesIO)time)READWRITEHubget_event_loop)	HttpError)bytes_to_str   )
BaseClientNCurl)GETPOSTPUTHEAD)
CurlClientz Mozilla/5.0 (compatible; pycurl)DELETEOPTIONSPATCHc                      s   e Zd ZdZeZd%ddd fddZd	d
 Zdd Zdd Zdd Z	e
fddZdd Ze
fddZe
fddZe
fddZe
fddZdd Zdd  Zdde
fd!d"Ze
fd#d$Z  ZS )&r   zCurl HTTP Client.N
   z
Hub | Noneint)hubmax_clientsc                   s   t d krtd|pt }t | | _t   _ jt j	 j
  jt j j  fddt|D  _ jd d   _t  _i  _ jj _ jd j _t  } j|  j| d S )Nz,The curl client requires the pycurl library.c                   s   g | ]}   qS  r   ).0iselfr   @/tmp/pip-unpacked-wheel-48hrr5dg/kombu/asynchronous/http/curl.py
<listcomp>3   s     z'CurlClient.__init__.<locals>.<listcomp>g      ?)pycurlImportErrorr
   super__init__r   Z	CurlMulti_multisetoptZM_TIMERFUNCTION_set_timeoutZM_SOCKETFUNCTION_handle_socketrange_curls
_free_listr   _pending_fdsZsocket_action_socket_actionr   Zcall_repeatedly_timeout_check_timeout_check_trefr   
add_handleremove_handle)r!   r   r   Zdummy_curl_handle	__class__r    r"   r'   )   s(    


 zCurlClient.__init__c                 C  s,   | j   | jD ]}|  q| j  d S N)r3   cancelr-   closer(   )r!   Z_curlr   r   r"   r:   B   s    


zCurlClient.closec                 C  s"   | j | |   | d |S Nr   )r/   append_process_queuer*   )r!   requestr   r   r"   add_requestH   s    
zCurlClient.add_requestc                 C  s   | j D ]}| j| qd S r8   )r0   r   remove)r!   fdr   r   r"   _pop_from_hubQ   s    
zCurlClient._pop_from_hubc                 C  sL   | j  D ]<\}}|t@ r,| j|| j| |t@ r
| j|| j| q
d S r8   )	r0   itemsr   r   Z
add_readeron_readabler   Z
add_writeron_writable)r!   rA   eventsr   r   r"   _push_to_hubU   s
    zCurlClient._push_to_hubc                 C  sl   ||j kr$|| jkrh| j|d  nD||jkr:t| j|< n.||jkrPt| j|< n||jkrhttB | j|< d S r8   )ZPOLL_REMOVEr0   popZPOLL_INr   ZPOLL_OUTr   Z
POLL_INOUT)r!   eventrA   Zmultidata_pycurlr   r   r"   r+   \   s    




zCurlClient._handle_socketc                 C  s   | j || j d S r8   )r   Z
call_laterr2   )r!   msecsr   r   r"   r*   h   s    zCurlClient._set_timeoutc              
   C  st   |    zTz| j \}}W n. tjk
rJ } z|jd }W 5 d }~X Y nX ||jkr
qZq
W 5 |   X |   d S r;   )	rB   rG   r(   Z
socket_allr$   errorargsE_CALL_MULTI_PERFORM_process_pending_requests)r!   rK   ret_excr   r   r"   r2   k   s    

zCurlClient._timeout_checkc                 C  s   |  ||jS r8   )	_on_eventZ
CSELECT_INr!   rA   rK   r   r   r"   rD   y   s    zCurlClient.on_readablec                 C  s   |  ||jS r8   )rT   ZCSELECT_OUTrU   r   r   r"   rE   |   s    zCurlClient.on_writablec              
   C  sv   |    zVz| ||\}}W n. tjk
rL } z|jd }W 5 d }~X Y nX ||jkr
q\q
W 5 |   X |   d S r;   )rB   rG   r1   r$   rM   rN   rO   rP   )r!   rA   rI   rK   rQ   rR   rS   r   r   r"   rT      s    

zCurlClient._on_eventc                 C  sZ   | j  \}}}|D ]}| | q|D ]\}}}| ||| q(|dkr qNq |   d S r;   )r(   Z	info_read_processr=   )r!   qZ	succeededfailedcurlerrnoreasonr   r   r"   rP      s    z$CurlClient._process_pending_requestsc                 C  sv   d}| j rj| jrj|d7 }| j  }| j }|  }t }|||t d|_| |||| | j	
| q|s qrq d S )Nr   r   )headersbufferr>   Zcurl_start_time)r.   r/   rH   popleftZHeadersr   r   info_setup_requestr(   r4   )r!   startedrY   r>   r\   bufr   r   r"   r=      s     

zCurlClient._process_queuec              
   C  s   |j d  }|_ | j| | j| |d }|rXd}t||}||_d }	|  d }n&d }||j	}||j
}	|d |d }
|
| j|
||d ||	|d d S )Nr]   iW  r   r>   r\   )r>   coder\   r]   effective_urlrM   )r_   r(   r5   r.   r<   r   rZ   r:   getinfoZ	HTTP_CODEZEFFECTIVE_URLseekZon_readyResponse)r!   rY   rZ   r[   rK   r_   r]   rc   rM   rd   r>   r   r   r"   rV      s0    

    zCurlClient._processc                   s0  |j }| jt|j |jdd |jdd | jdd |j D  | jt	|j
pb| j
|j | j|jp||j | j|j | jt|jpt |jr| j|j | j|jrdnd |jr&|jstd| j|j | j|j |jr&| jd	|j|jp d | j |j!r8d
nd | j"|j!rPdnd |j#d k	rp| j$|j# | j%t&j' t() D ]}||d qzt(|j* }W n& t+k
r   |  j,|j* Y nX |- j, ||d |j*dkrh|j.r|j./dnd}t0|| j1j2 |j*dkrV fdd}	| j3|	 | j4t5| n| j6t5| n|j*dkr|j.rt7|j8d k	rֈ j9 j:d|j;pd }
| j<|
 d	|j8|j=pd}| j>| n|- j> |j?d k	r| j@|j? |jAd k	r| jB|jA |jCd k	r,|C| d S )NZExpect ZPragmac                 S  s   g | ]}d j | qS )z{}: {})format)r   hr   r   r"   r#      s     z-CurlClient._setup_request.<locals>.<listcomp>zgzip,deflatenonez)Request with proxy_host but no proxy_portz{}:{}r   r      FT)r   r   zutf-8    r   c                   s   |  j krd d S r;   )ZIOCMD_RESTARTREADrf   )cmdrK   Z	reqbufferr   r"   ioctl  s    
z(CurlClient._setup_request.<locals>.ioctlr   )basicdigestrq   )Dr)   URLr   urlr\   
setdefaultZ
HTTPHEADERrC   ZHEADERFUNCTIONr   Z	on_headerZWRITEFUNCTIONZ	on_streamwriteZFOLLOWLOCATIONZfollow_redirectsZ	USERAGENT
user_agentDEFAULT_USER_AGENTZnetwork_interfaceZ	INTERFACEENCODINGZuse_gzipZ
proxy_hostZ
proxy_port
ValueErrorZPROXYZ	PROXYPORTZproxy_usernameZPROXYUSERPWDri   Zproxy_passwordZSSL_VERIFYPEERZvalidate_certZSSL_VERIFYHOSTca_certsZCAINFOZ	IPRESOLVEr$   ZIPRESOLVE_WHATEVERMETH_TO_CURLvaluesmethodKeyErrorZCUSTOMREQUESTZunsetoptbodyencoder   ZREADFUNCTIONreadZIOCTLFUNCTIONZPOSTFIELDSIZElenZ
INFILESIZEAssertionErrorZauth_usernameZHTTPAUTH_BASICZHTTPAUTH_DIGEST	auth_modeZHTTPAUTHZauth_passwordZUSERPWDclient_certZSSLCERTZ
client_keyZSSLKEYZ
on_prepare)r!   rY   r>   r]   r\   rK   r)   methr   rp   r   Zuserpwdr   ro   r"   r`      s     
  
 


 
zCurlClient._setup_request)Nr   )__name__
__module____qualname____doc__r   r'   r:   r?   rB   rG   r$   r+   r*   r2   rD   rE   rT   rP   r=   rV   r`   __classcell__r   r   r6   r"   r   $   s"   	r   )"r   
__future__r   collectionsr   	functoolsr   ior   r   Zkombu.asynchronous.hubr   r   r	   r
   Zkombu.exceptionsr   Zkombu.utils.encodingr   baser   r$   r%   r   r|   ZHTTPGETr   ZUPLOADZNOBODY__all__rx   	frozensetZEXTRA_METHODSr   r   r   r   r"   <module>   s.   