U
    Y+d%                     @   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	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.    )deque)partial)BytesIO)time)READWRITE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" 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
   c                    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-rdvd7wfc/kombu/asynchronous/http/curl.py
<listcomp>1   s     z'CurlClient.__init__.<locals>.<listcomp>g      ?)pycurlImportErrorr   super__init__max_clientsZ	CurlMulti_multisetoptZM_TIMERFUNCTION_set_timeoutZM_SOCKETFUNCTION_handle_socketrange_curls
_free_listr   _pending_fdsZsocket_action_socket_actionhubZ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)r0   cancelr)   closer$   )r   Z_curlr   r   r   r7   @   s    


zCurlClient.closec                 C   s"   | j | |   | d |S Nr   )r+   append_process_queuer&   )r   requestr   r   r   add_requestF   s    
zCurlClient.add_requestc                 C   s   | j D ]}| j| qd S r5   )r,   r.   remove)r   fdr   r   r   _pop_from_hubO   s    
zCurlClient._pop_from_hubc                 C   sL   | j  D ]<\}}|t@ r,| j|| j| |t@ r
| j|| j| q
d S r5   )	r,   itemsr   r.   Z
add_readeron_readabler   Z
add_writeron_writable)r   r>   eventsr   r   r   _push_to_hubS   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 r5   )ZPOLL_REMOVEr,   popZPOLL_INr   ZPOLL_OUTr   Z
POLL_INOUT)r   eventr>   Zmultidata_pycurlr   r   r   r'   Z   s    




zCurlClient._handle_socketc                 C   s   | j || j d S r5   )r.   Z
call_laterr/   )r   msecsr   r   r   r&   f   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 r8   )	r?   rD   r$   Z
socket_allr   errorargsE_CALL_MULTI_PERFORM_process_pending_requests)r   rH   ret_excr   r   r   r/   i   s    

zCurlClient._timeout_checkc                 C   s   |  ||jS r5   )	_on_eventZ
CSELECT_INr   r>   rH   r   r   r   rA   w   s    zCurlClient.on_readablec                 C   s   |  ||jS r5   )rQ   ZCSELECT_OUTrR   r   r   r   rB   z   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 r8   )r?   rD   r-   r   rJ   rK   rL   rM   )r   r>   rF   rH   rN   rO   rP   r   r   r   rQ   }   s    

zCurlClient._on_eventc                 C   sZ   | j  \}}}|D ]}| | q|D ]\}}}| ||| q(|dkr qNq |   d S r8   )r$   Z	info_read_processr:   )r   qZ	succeededfailedcurlerrnoreasonr   r   r   rM      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+   rE   popleftZHeadersr   r   info_setup_requestr$   r1   )r   startedrV   r;   rY   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 )NrZ   iW  r   r;   rY   )r;   coderY   rZ   effective_urlrJ   )r\   r$   r2   r*   r9   r	   rW   r7   getinfoZ	HTTP_CODEZEFFECTIVE_URLseekZon_readyResponse)r   rV   rW   rX   rH   r\   rZ   r`   rJ   ra   r;   r   r   r   rS      s0    

    zCurlClient._processc                    s2  |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rj|j.r|j./dnt0 }t1|| j2j3 |j*dkrX fdd}	| j4|	 | j5t6| n| j7t6| n|j*dkr|j.rt8|j9d k	r؈ j: j;d|j<pd }
| j=|
 d	|j9|j>pd}| j?| n|- j? |j@d k	r| jA|j@ |jBd k	r| jC|jB |jDd k	r.|D| 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-8r   c                    s   |  j krd d S r8   )ZIOCMD_RESTARTREADrc   )cmdrH   Z	reqbufferr   r   ioctl  s    
z(CurlClient._setup_request.<locals>.ioctlr   )basicdigestrm   )Er%   URLr
   urlrY   
setdefaultZ
HTTPHEADERr@   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PROXYUSERPWDrf   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encodebytesr   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   rV   r;   rZ   rY   rH   r%   methr|   rl   r   Zuserpwdr   rk   r   r]      s     
  
 


 
zCurlClient._setup_request)Nr   )__name__
__module____qualname____doc__r   r"   r7   r<   r?   rD   r   r'   r&   r/   rA   rB   rQ   rM   r:   rS   r]   __classcell__r   r   r3   r   r   "   s"   	r   )r   collectionsr   	functoolsr   ior   r   Zkombu.asynchronous.hubr   r   r   Zkombu.exceptionsr	   Zkombu.utils.encodingr
   baser   r   r    r   rx   ZHTTPGETr   ZUPLOADZNOBODY__all__rt   	frozensetZEXTRA_METHODSr   r   r   r   r   <module>   s,   