
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
Ö;jE  ã               @   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mZmZm	Z	m
Z
 ddlmZmZmZmZmZmZ dd„ Zdd	d
„Zdd„ Zdd„ Zddd„Zdd„ Zdd„ Zeƒ Ze
jed�ddd„ƒZdS )é    N)ÚSSLErroré   )ÚconfigÚ	constantsÚerrorsÚ	log_utilsÚutils)Ú	HTTPErrorÚRequestÚURLErrorÚhttplibÚstd_urlopenÚurlparsec       	      O   s¨  t | dƒr| jƒ }n| }t| ƒ} |jdi ƒ}|jtjtjdœƒ x |jƒ D ]\}}| j	||ƒ qJW t
jdj||ƒƒ ydd|krˆtj|d< tj rÊttdd ƒrÊtjƒ }d|_tj|_||d< t| f|ž|ŽS t| f|ž|ŽS  tk
�r& } z0|jd	k�rtj|j|j|j|j|jƒ‚‚ W Y d d }~X n~ tk
�r¢ } z`|j �r|t |j d
 dƒ�r||j d
 j!t!j"k�r|tj| d	t#|ƒd d ƒ‚dj||ƒ|_$||_‚ W Y d d }~X nX d S )NÚget_full_urlÚheaders)z
KC-VersionzKC-Patch-Versionz#Requesting url: `{0}`. Headers: {1}ÚtimeoutÚHAS_SNIFÚcontexti”  r   ÚerrnozRequest for `{0}` failed: {1})%Úhasattrr   r
   ÚpopÚupdater   ÚVERSIONÚKC_PATCH_VERSIONÚitemsÚ
add_headerr   ÚlogdebugÚformatr   ÚHTTP_TIMEOUTÚCHECK_SSL_CERTSÚgetattrÚsslÚcreate_default_contextÚcheck_hostnameÚ	CERT_NONEÚverify_moder   r	   Úcoder   ÚNotFoundÚurlÚmsgÚhdrsÚfpr   Úargsr   ÚENOENTÚstrÚreason)	r(   r,   ÚkwargsZrequest_urlr   ÚheaderÚvalueÚctxÚex© r5   ú0/usr/libexec/kcare/python/kcarectl/http_utils.pyÚurlopen_base   s>    


.r7   Tc                s   ‡ fdd„}|S )Nc                sb   t | tƒrˆ o| jdkS t | ttjttjfƒr2dS t	| dƒr^t
| jƒdkr^| jd tjkr^dS d S )Niô  Tr,   é   r   )Ú
isinstancer	   r&   r   r   ÚHTTPExceptionr   Úsocketr   r   Úlenr,   r   Z
ECONNRESET)ÚeÚstate)Úretry_on_500r5   r6   Úcheck_functionC   s    
(z3check_urlopen_retry_factory.<locals>.check_functionr5   )r?   r@   r5   )r?   r6   Úcheck_urlopen_retry_factoryB   s    	rA   c             C   s   t | dƒr| jƒ } | jdƒS )Nr   zfile:)r   r   Ú
startswith)r(   r5   r5   r6   Úis_local_urlO   s    
rC   c             O   sV   |j ddƒ}|j dtjƒ}t| ƒr2t| f|ž|ŽS tjt|d�|d�tƒ| f|ž|ŽS )Nr?   TÚretry_count)r?   )Úcount)r   r   ÚRETRY_COUNTrC   r7   r   ÚretryrA   )r(   r,   r0   r?   rD   r5   r5   r6   ÚurlopenU   s
    rH   c             C   sH   t | |d�}tj r*|r*|jddj|ƒƒ tj rD|rD|jtj|ƒ |S )N)ÚmethodÚAuthorizationz	Basic {0})r
   r   ÚUPDATE_FROM_LOCALr   r   r   ÚAUTH_TOKEN_HEADER)r(   Úauth_stringÚ
auth_tokenrI   Úrequestr5   r5   r6   Úhttp_request]   s    rP   c             C   s<   | dkrt jdƒpt jdƒS | dkr8t jdƒp6t jdƒS d S )NÚhttpZ
http_proxyZ
HTTP_PROXYÚhttpsZhttps_proxyZHTTPS_PROXY)ÚosÚgetenv)Úschemer5   r5   r6   Úget_proxy_from_envh   s    rV   c               C   s   t tdƒƒpt tdƒƒS )NrQ   rR   )ÚboolrV   r5   r5   r5   r6   Úproxy_is_usedo   s    rX   )Zcheck_retryc             C   sÂ  t jj| ƒ}|stdj| ƒƒ‚ttj|ƒƒ}|j}|j	}|jp@d}|dkrRtdƒ‚|dkrl|j
dkrhdnd}|j
dkr~tj}n|j
dkr�tj}ntd	ƒ‚|||tjd
�}	i }
|r¾dj|ƒ|
d< d|
d< t|ƒ|
d< tj|
d< zÖ|	jd|ƒ x |
jƒ D ]\}}|	j||ƒ qôW |	jƒ  t| dƒ�}|	j|ƒ W dQ R X |	jƒ }|jdk�r°y|jƒ }W n tk
�rn   d}Y nX dj|jƒ}|dk	�r”|dj|ƒ7 }tj|ƒ t||j|ddƒ‚W d|	j ƒ  X dS )aŽ  Upload a file to the given URL using HTTP PUT with chunked streaming.
    Note: The standard library urllib doesn't support PUT with data
    We need to use httplib directly for this

    This function uses streaming upload to support large files up to 1GB
    without loading the entire file into memory.

    :param file_path: Path to the file to upload
    :param upload_url: Full URL to upload the file to. Query params are ignored.
    :param auth_string: Optional authentication string for Basic Auth
    :return: None if upload succeeded
    :raises HTTPError: If upload fails with HTTP status >= 400
    :raises ValueError: If URL is invalid
    z"Refusing to upload empty file: {0}ú/NzInvalid URL: missing hostnamerR   i»  éP   rQ   zInvalid URL: unsupported scheme)r   z	Basic {0}rJ   zapplication/octet-streamzContent-TypezContent-Lengthz
KC-VersionÚPUTÚrbi�  zFailed to upload file: HTTP {0}z - {0})!rS   ÚpathÚgetsizeÚ
ValueErrorr   r   r   ÚnstrÚhostnameÚportrU   r   ÚHTTPConnectionÚHTTPSConnectionr   ÚHTTP_UPLOAD_TIMEOUTr.   r   r   Ú
putrequestr   Ú	putheaderÚ
endheadersÚopenÚsendÚgetresponseÚstatusÚreadÚ	Exceptionr   Úlogerrorr	   Úclose)Z	file_pathÚ
upload_urlrM   Z	file_sizeÚparsedÚhostrb   Zurl_pathZconn_clsÚconnr   r1   r2   ÚfÚresponseZ
error_bodyÚ	error_msgr5   r5   r6   Úupload_filev   sT    






rx   )T)NN)N)r   rS   r;   r!   r   Ú r   r   r   r   r   Úpy23r	   r
   r   r   r   r   r7   rA   rC   rH   rP   rV   rX   Úcheck_urlopen_retryrG   rx   r5   r5   r5   r6   Ú<module>   s     0


