a ƒ¬ iã@sÄddlZddlZddlZddlZddlmZddlmZm Z m Z m Z m Z ddl mZmZmZmZmZmZdd„Zdd d „Zd d „Zd d„Zddd„Zdd„Zdd„ZeƒZe jedddd„ƒZdS)éN)ÚSSLErroré)ÚconfigÚ constantsÚerrorsÚ log_utilsÚutils)Ú HTTPErrorÚRequestÚURLErrorÚhttplibÚ std_urlopenÚurlparsec Os¼t|dƒr| ¡}n |}t|ƒ}| di¡}| tjtjdœ¡| ¡D]\}}|  ||¡qHt   d  ||¡¡zxtj sŠd|vrŠtj|d<tjsÒttddƒrÒt ¡}d|_tj|_||d<t|g|¢Ri|¤ŽWSt|g|¢Ri|¤ŽWSty8}z6|jd kr"t |j|j|j|j|j¡‚‚WYd}~nˆd}~0t y¶}zf|j!rŒt|j!d d ƒrŒ|j!d j"t"j#krŒt |d t$|ƒdd¡‚d   ||¡|_%||_‚WYd}~n d}~00dS) NÚ get_full_urlÚheaders)ú KC-VersionzKC-Patch-Versionz#Requesting url: `{0}`. Headers: {1}ÚtimeoutÚHAS_SNIFÚcontexti”rÚerrnozRequest for `{0}` failed: {1})&Úhasattrrr ÚpopÚupdaterÚVERSIONÚKC_PATCH_VERSIONÚitemsÚ add_headerrÚlogdebugÚformatÚPY2_6rÚ 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©r7ú0/usr/libexec/kcare/python/kcarectl/http_utils.pyÚ urlopen_basesB   þÿ  .r9Tcs‡fdd„}|S)Ncsbt|tƒrˆo|jdkSt|ttjttjfƒr2dSt |dƒr^t |j ƒdkr^|j dt j kr^dSdS)NiôTr.ér)Ú isinstancer r(r r Ú HTTPExceptionrÚsocketrrÚlenr.rZ ECONNRESET)ÚeÚstate©Ú retry_on_500r7r8Úcheck_functionDs  (z3check_urlopen_retry_factory..check_functionr7)rBrCr7rAr8Úcheck_urlopen_retry_factoryCs rDcCst|dƒr| ¡}| d¡S)Nrzfile:)rrÚ startswith)r*r7r7r8Ú is_local_urlPs rFcOsb| dd¡}| dtj¡}t|ƒr8t|g|¢Ri|¤ŽStjt|d|dtƒ|g|¢Ri|¤ŽS)NrBTÚ retry_countrA)Úcount)rrÚ RETRY_COUNTrFr9rÚretryrD)r*r.r2rBrGr7r7r8ÚurlopenVs  rKcCsDt||d}tjs(|r(| dd |¡¡tjs@|r@| tj|¡|S)N)ÚmethodÚ Authorizationú Basic {0})r rÚUPDATE_FROM_LOCALrrrÚAUTH_TOKEN_HEADER)r*Ú auth_stringÚ auth_tokenrLÚrequestr7r7r8Ú http_request^s    rTcCs<|dkrt d¡pt d¡S|dkr8t d¡p6t d¡SdS)NÚhttpZ http_proxyZ HTTP_PROXYÚhttpsZ https_proxyZ HTTPS_PROXY)ÚosÚgetenv)Úschemer7r7r8Úget_proxy_from_envisrZcCsttdƒƒpttdƒƒS)NrUrV)ÚboolrZr7r7r7r8Ú proxy_is_usedpsr\)Z check_retrycCsòtj |¡}|std |¡ƒ‚tt |¡ƒ}|j}|j }|jp@d}|durRtdƒ‚|durl|j dkrhdnd}|j dkr~t j }n|j dkrt j }ntd ƒ‚tjr¢ind tji} |||fi| ¤Ž} i} |rÔd  |¡| d <d | d<t|ƒ| d<tj| d<zð|  d|¡|  ¡D]\} } |  | | ¡q|  ¡t|dƒ}|  |¡Wdƒn1sT0Y|  ¡}|jdkrØz | ¡}Wnty–d}Yn0d |j¡}|dur¼|d |¡7}t |¡t ||j|ddƒ‚W|  !¡n |  !¡0dS)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}ú/NzInvalid URL: missing hostnamerVi»éPrUzInvalid URL: unsupported schemerrNrMzapplication/octet-streamz Content-TypezContent-LengthrÚPUTÚrbizFailed to upload file: HTTP {0}z - {0})"rWÚpathÚgetsizeÚ ValueErrorrrrÚnstrÚhostnameÚportrYr ÚHTTPConnectionÚHTTPSConnectionrrrÚHTTP_UPLOAD_TIMEOUTr0rÚ putrequestrÚ putheaderÚ endheadersÚopenÚsendÚ getresponseÚstatusÚreadÚ ExceptionrÚlogerrorr Úclose)Z file_pathÚ upload_urlrQÚ file_sizeÚparsedÚhostrfZurl_pathZconn_clsZ conn_kwargsÚconnrr3r4ÚfÚresponseZ error_bodyÚ error_msgr7r7r8Ú upload_filewsV        *      r})T)NN)N)rrWr=r#rÚOptionalÚUnionÚrrrrrÚpy23r r r r r rr9rDrFrKrTrZr\Úcheck_urlopen_retryrJr}r7r7r7r8Ús   1