o
    M                     @   s  d Z ddl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ZddlZddl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 ddlmZ ddl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"m#Z$ ddl"m%Z% ddl&Z&ddl'm(Z( zddl)m*Z+ W n e,y   ddl%Z+Y nw dZ-da.							dHddZ/G dd de0dg dZ1dd Z2G dd dej3j4Z4dd  Z5d!Z6G d"d# d#e7Z8G d$d% d%ej3j4Z9d&ej:d'ej3j;fd(d)Z<d*d+ Z=						dId,d-Z>		dJd.d/Z?d0d1 Z@G d2d3 d3ejAZAG d4d5 d5ejBZBG d6d7 d7ejCZCd8d9 ZDG d:d; d;ZEdKd<d=ZFG d>d? d?e!GejHZIG d@dA dAZJdBdC ZKdDdE ZLdFdG ZMdS )Lz;A module to get an unauthenticated requests.Session object.    )absolute_import)division)unicode_literalsN)requests)_MutualTlsOffloadAdapter)context_aware)execution_utils)log)
properties)	transport)encoding)http_proxy_types)	platforms)http_client)urllibcreate_urllib3_contextah  It appears that the current proxy configuration is using an HTTPS scheme for contacting the proxy server, which likely indicates an error in your HTTPS_PROXY environment variable setting. This can usually be resolved by setting HTTPS_PROXY=http://... instead of HTTPS_PROXY=https://... See https://cloud.google.com/sdk/docs/proxy-settings for more information.Funsetc                 C   s&   t | ||||}t j|||d}|S )a3  Get a requests.Session that is properly configured for use by gcloud.

  This method does not add credentials to the client. For a requests.Session
  that has been authenticated, use core.credentials.requests.GetSession().

  Args:
    timeout: double, The timeout in seconds. This is the
        socket level timeout. If timeout is None, timeout is infinite. If
        default argument 'unset' is given, a sensible default is selected using
        transport.GetDefaultTimeout().
    ca_certs: str, absolute filename of a ca_certs file that overrides the
        default. The gcloud config property for ca_certs, in turn, overrides
        this argument.
    session: requests.Session instance
    streaming_response_body: bool, True indicates that the response body will
        be a streaming body.
    redact_request_body_reason: str, the reason why the request body must be
        redacted if --log-http is used. If None, the body is not redacted.
    client_certificate: str, absolute filename of a client_certificate file that
        is set explicitly for client certificate authentication
    client_key: str, absolute filename of a client_key file that
        is set explicitly for client certificate authentication

  Returns:
    A requests.Session object configured with all the required settings
    for gcloud.
  )streaming_response_bodyredact_request_body_reason)_CreateRawSessionRequestWrapperWrapWithDefaults)timeoutca_certssessionr   r   client_certificate
client_keyr    r   9/tmp/google-cloud-sdk/lib/googlecloudsdk/core/requests.py
GetSessionE   s   "r    c                       "   e Zd ZdZd fdd	Z  ZS )ClientSideCertificatezHolds information about a client side certificate.

  Attributes:
    certfile: str, path to a cert file.
    keyfile: str, path to a key file.
    password: str, password to the private key.
  Nc                    s   t t| | |||S N)superr"   __new__)clscertfilekeyfilepassword	__class__r   r   r%   {   s   
zClientSideCertificate.__new__r#   )__name__
__module____qualname____doc__r%   __classcell__r   r   r*   r   r"   p   s    r"   )r'   r(   r)   c                   C   s   t  S )zReturns a urrlib3 SSL context.r   r   r   r   r   CreateSSLContext   s   r1   c                       s@   e Zd ZdZ fddZ fddZ fddZdd	 Z  ZS )
HTTPAdaptera=  Transport adapter for requests.

  Transport adapters provide an interface to extend the default behavior of the
  requests library using the full power of the underlying urrlib3 library.

  See https://requests.readthedocs.io/en/master/user/advanced/
      #transport-adapters for more information about adapters.
  c                    s    || _ tt| j|i | d S r#   )
_cert_infor$   r2   __init__)selfclient_side_certificateargskwargsr*   r   r   r4      s   zHTTPAdapter.__init__c                        |  | tt| j|i |S r#   )_add_ssl_contextr$   r2   init_poolmanagerr5   r7   r8   r*   r   r   r;         
zHTTPAdapter.init_poolmanagerc                    r9   r#   )r:   r$   r2   proxy_manager_forr<   r*   r   r   r>      r=   zHTTPAdapter.proxy_manager_forc                 C   sf   | j sd S t }|  i }| j jr| j j|d< | j jr"| j j|d< |j| j jfi | ||d< d S )Nr(   r)   ssl_context)r3   r1   load_default_certsr(   r)   load_cert_chainr'   )r5   r8   contextcert_chain_kwargsr   r   r   r:      s   zHTTPAdapter._add_ssl_context)	r,   r-   r.   r/   r4   r;   r>   r:   r0   r   r   r*   r   r2      s    	r2   c            
      C   s$  t jjj } t jjj }t jjj }tdd | ||fD }|dkr.|dkr.t 	d|s2dS t jjj
 }t jjj }t jjj }tj|  }|tjkrX|rUdnd}n|tjkrd|rad	nd
}n|tjkrld}ntd| |sw|rddd ||fD }	|	d7 }	nd}	d||	||S )zReturns the proxy string for use by requests from gcloud properties.

  See https://requests.readthedocs.io/en/master/user/advanced/#proxies.
  c                 S   s   g | ]}|r|qS r   r   ).0fr   r   r   
<listcomp>   s    z GetProxyInfo.<locals>.<listcomp>r      z\Please set all or none of the following properties: proxy/type, proxy/address and proxy/portNsocks4asocks4socks5hsocks5httpzUnsupported proxy type: {}:c                 s   s     | ]}t j|pd V  qdS ) N)r   parsequote)rD   xr   r   r   	<genexpr>   s    
zGetProxyInfo.<locals>.<genexpr>@rN   z{}://{}{}:{})r
   VALUESproxy
proxy_typeGetaddressportGetIntlenInvalidValueErrorrdnsGetBoolusernamer)   r   PROXY_TYPE_MAPsocksPROXY_TYPE_SOCKS4PROXY_TYPE_SOCKS5PROXY_TYPE_HTTP
ValueErrorformatjoin)
rV   proxy_address
proxy_portproxy_prop_set
proxy_rdns
proxy_user
proxy_passhttp_proxy_typeproxy_scheme
proxy_authr   r   r   GetProxyInfo   s@   






rq   a  Please use the installed gcloud CLI (`apt install google-cloud-cli`)
 This version of gcloud you are currently using will encounter issues due to
 changes in internal security policy enforcement in the near future.

 If this is not possible due to dev requirements, please apply for
 policy exemption at go/gcloud-cba-exemption-internal-version-gcloud using this error message to self-exempt or reach out to
 go/gcloud-cba-investigation for investigation.
c                       r!   )ECPProxyErrorzCustom exception for errors related to the ECP proxy communication.

  For example, startup failures or receiving a specific proxy error header.
  Nc                    s.   || _ t |r| d|  d S | d S )N: )original_exceptionr$   r4   )r5   messagert   r*   r   r   r4      s   zECPProxyError.__init__r#   )r,   r-   r.   r/   r4   r0   r   r   r*   r   rr      s    rr   c                       s   e Zd ZdZ		ddededef fddZd	efd
dZ	ddeded	efddZdeded	dfddZ	deded	dfddZ
 fddZdd Z fddZ  ZS )_LocalECPProxyAdaptera+  A requests adapter that routes HTTPS requests through a local ECP proxy.

  This adapter starts the ECP proxy as a background process upon instantiation
  and manages its lifecycle, terminating it when the adapter is closed.
  This avoids the overhead of starting a new process for every request.
  N   certificate_config_file_pathgcloud_proxy_urlstartup_timeoutc                    sV   || _ || _t jdi | t| j d| _d| _t	
d| _| j|dd| _dS )ab  Initializes the adapter and starts the local ECP proxy process.

    Args:
        certificate_config_file_path: Path to the JSON certificate config file.
        gcloud_proxy_url: Optional URL for proxy chaining.
        startup_timeout: Seconds to wait for the proxy to become available.
        **kwargs: Additional arguments for the HTTPAdapter.
    N	localhost      )max_retriesr   )rx   ry   r$   r4   atexitregistercloseproxy_process
proxy_hostsecrets	token_hexnonce_token_start_ecp_proxy_with_retriesri   )r5   rx   ry   rz   r8   r*   r   r   r4      s   z_LocalECPProxyAdapter.__init__returnc                 C   sB   t   }|d | d W  d   S 1 sw   Y  dS )z4Dynamically finds and returns an available TCP port.)rN   r   r}   N)socketbindgetsockname)r5   sr   r   r   _find_free_port  s   


$z%_LocalECPProxyAdapter._find_free_portr}   r   r~   c                 C   s   t | j}|di d}|std| jt|d D ]U}|  }| j||d z| j	||d |W   S  tyt } z0| j
rO| j
 du rO| j
  ||k rdtd| d	|  W Y d}~qtd
| d|   d}~ww dS )a  Attempts to start the ECP Proxy, retrying on failure.

    This method orchestrates the proxy startup by finding an available port,
    launching the proxy process, and waiting for it to become responsive.
    If the proxy fails to start, it retries the process until either succeeds
    or the maximum number of retries is reached.

    Args:
      timeout: The maximum time in seconds to wait for the proxy to start
      max_retries: The maximum number of times to retry starting the proxy.

    Returns:
      The port number on which the proxy successfully started.

    Raises:
      ECPProxyError: If the proxy fails to start after all retry attempts.
    libsecp_http_proxya  ECP HTTP proxy binary path is not specified in enterprise certificate config file. Cannot use mTLS with ECP if the ECP HTTP proxy binary does not exist. Please check the ECP configuration. See `gcloud topic client-certificate` to learn more about ECP. 
If this error is unexpected either delete {} or generate a new configuration with `$ gcloud auth enterprise-certificate-config create --help` r}   )r   ri   )ri   r   Nz"ECP proxy failed to start on port rs   z ECP proxy failed to start after z
 retries: )r   GetCertificateConfigrx   getrr   rf   ranger   _start_ecp_proxy_wait_for_proxyr   poll	terminater	   warningerror)r5   r   r~   cert_configr   attemptri   er   r   r   r     s8   


z3_LocalECPProxyAdapter._start_ecp_proxy_with_retriesr   ri   c             
   C   s   t d|  d| jdt|d| jg}| jr|d| jg tj|g|R  }zt	j
|ddd| _W dS  ttfyQ } zt d|  td	|d
|d}~ww )a	  Launches the local ECP proxy executable as a subprocess.

    Constructs the necessary command-line arguments, including the ECP config
    path, port, nonce token, and an optional upstream proxy URL. It then uses
    subprocess.Popen to start the proxy process in the background.

    Args:
      ecp_http_proxy: The path to the ECP HTTP proxy binary.
      proxy_port: The TCP port for the proxy to listen on.

    Raises:
      ECPProxyError: If the subprocess fails to start due to OSError or
        ValueError.
    z(Starting local ECP proxy server on port z!-enterprise_certificate_file_pathz-portz-nonce_tokenz%-gcloud_configured_upstream_proxy_urlN)stdoutstderrz&Failed to start ECP proxy executable: z!Failed to start ECP proxy processrt   )r	   debugrx   strr   ry   extendr   ArgsForExecutableTool
subprocessPopenr   OSErrorre   r   rr   )r5   r   ri   r7   
proxy_argsr   r   r   r   r   T  s8   	z&_LocalECPProxyAdapter._start_ecp_proxyc             
   C   sn  t d| d t }t | |k r[| j dur&td| jj dztj	| j
|fdd
 	 W d   W n31 s>w   Y  W n tyR   td Y qw t | |k s|   td| j
 d	| d
| dz3d| j
 d	| d}tj|dd}|jdkrtd|j d|j}|| jkrtdt d W dS  tjjy } ztd|d|d}~ww )a  Waits for the proxy to become available and verifies its identity.

    This method first waits for the proxy's TCP port to accept connections.
    Once the port is open, it sends a request to the `/readyz` endpoint to
    confirm that the proxy is fully operational and to verify a security nonce,
    ensuring that gcloud is communicating with the correct proxy instance.

    Args:
      proxy_port: The port where the proxy is expected to be listening.
      timeout: The maximum time in seconds to wait for the proxy.

    Raises:
      ECPProxyError: If the proxy process terminates unexpectedly, fails to
        respond within the timeout, or returns an invalid nonce.
    z*Waiting for the proxy to be ready on port z...Nz0Proxy process terminated unexpectedly with code z while waiting for it to start.g?r   zECP Proxy on rM   z did not become ready in z	 seconds.http://z/readyzr}      z'Proxy /readyz endpoint returned status .z+Nonce mismatch from proxy /readyz endpoint.z"Proxy is ready and nonce verified.z6Failed to verify proxy readiness via /readyz endpoint.r   )r	   r   time	monotonicr   r   rr   
returncoder   create_connectionr   r   sleepr   r   r   status_codetextr   
exceptionsRequestException)r5   ri   r   
start_time
readyz_urlresponseserver_noncer   r   r   r   r     s\   
$


z%_LocalECPProxyAdapter._wait_for_proxyc              
      s   t j|j}|j|jd< t jdd|j|jdf}d| j	 d| j
 | |_d|d< td|  d|j  zt j|fi |}W n tjjyZ } ztd	|d
|d}~ww | |S )a  Intercepts an outgoing request and reroutes it through the local ECP proxy.

    This method modifies the request's URL to point to the local proxy and
    adds a custom header (`x-goog-ecpproxy-target-host`) to inform the proxy
    of the original destination. It then sends the modified request and passes
    the response to `_handle_proxy_response` for inspection.

    Args:
      request: The `requests.PreparedRequest` object to send.
      **kwargs: Additional arguments passed to the underlying `send` method.

    Returns:
      The `requests.Response` object from the proxy.

    Raises:
      ECPProxyError: If the proxy returns an error or fails to send the request.
    zx-goog-ecpproxy-target-hostrN   r   rM   FverifyzRedirecting request for z to proxy at zFailed to send request to proxyr   N)r   rO   urlspliturlhostnameheaders
urlunsplitpathqueryr   ri   r	   r   geturlr$   sendr   r   r   rr   _handle_proxy_response)r5   requestr8   original_url
proxy_pathr   r   r*   r   r   r     s.   
z_LocalECPProxyAdapter.sendc                 C   sj   |j d}|r3td z| dd}d| }W t| tjy2   d|j }Y t|w |S )aS  Inspects the proxy's response for custom error headers.

    If the `x-goog-ecpproxy-error` header is present in the response, this
    method assumes the proxy encountered an internal error. It attempts to parse
    a detailed error message from the JSON response body and raises an
    `ECPProxyError` with the relevant information.

    Args:
      response: The `requests.Response` object received from the proxy.

    Returns:
      The original `requests.Response` object if no error header is found.

    Raises:
      ECPProxyError: If the `x-goog-ecpproxy-error` header is present.
    zx-goog-ecpproxy-errorzECP Proxy returned an errorru   zNo message in body.z'ECP Proxy indicated an internal error: z6ECP Proxy indicated an internal error. Response body: )r   r   r	   r   jsonJSONDecodeErrorr   rr   )r5   r   proxy_error_headererror_detailsru   r   r   r   r     s   
z,_LocalECPProxyAdapter._handle_proxy_responsec                    sr   t d | jr2| j du r2| j  z	| jjdd W n tjy1   t d | j	  Y nw t
   dS )a  Terminates the background ECP proxy process to clean up resources.

    This method ensures that the local proxy subprocess is properly shut down
    when the session is closed. It first attempts a graceful termination and
    waits briefly, then forcefully kills the process if it does not exit in
    time. Finally, it calls the parent class's `close` method to complete
    the cleanup.
    z:Closing ECP Proxy Adapter and terminating proxy process...Ng      ?r   z7Proxy process did not terminate gracefully, killing it.)r	   r   r   r   r   waitr   TimeoutExpiredr   killr$   r   )r5   r*   r   r   r     s   
	

z_LocalECPProxyAdapter.close)Nrw   )r}   )r,   r-   r.   r/   r   intr4   r   r   r   r   r   r   r   r0   r   r   r*   r   rv      s2    
 
6,E0!rv   	ca_configr   c                 C   s.   | r| j s	td| jrt| j dS t| j S )a  Creates a requests adapter for mTLS offloading via ECP.

  This function decides which adapter to use based on the provided
  configuration:
  - If `ca_config.use_local_proxy` is True, it returns a
    `_LocalECPProxyAdapter`, which routes traffic through a local ECP proxy
    subprocess.
  - Otherwise, it returns a `_MutualTlsOffloadAdapter` from the google-auth
    library, which uses the ECP binary for TLS offloading without a local proxy.

  Args:
      ca_config: The enterprise certificate configuration object.

  Returns:
      An instance of a requests adapter for mTLS offloading.

  Raises:
      ValueError: If the certificate configuration file path is not provided.
  z.Certificate config file path must be provided.)rx   )rx   re   use_local_proxyrv   r   )r   r   r   r   _CreateMutualTlsOffloadAdapter+  s   

r   c                  C   sH   t j t jjk} tjodtjv }t }| r"|s"|r"t	t
 dS dS )ai  Warn users if running non-bundled Python on Linux and is a Googler.

  Checks if the current OS is Linux, running Python that is not bundled and if
  the user is a Googler. If all conditions are true, a warning message will be
  emitted, along with returning true to bypass the mTLS code path.

  Returns:
    True if the conditions are met, False otherwise.
  bundledTF)r   OperatingSystemCurrentLINUXsys
executabler
   IsInternalUserCheckr	   r   _GOOGLER_BUNDLED_PYTHON_WARNING)is_linuxis_bundled_pythonis_internal_userr   r   r   %_LinuxNonbundledPythonAndGooglerCheckL  s   
r   c           
         s8  |pt  }t |j  fdd}||_r#d|_d|_nt r/ts/dat	t
 d}|durO|durO|durOtd||| t||}t|}n:t }	|	rt  |	jtjjkrdt|	}n%|	jtjjkrtd|	j t|	j|	j|	j}t|}n	td}ntd}|rd|_n|r||_|d	| |S )
a  Returns a requests.Session subclass.

  Args:
    timeout: float, Request timeout, in seconds.
    ca_certs: str, absolute filename of a ca_certs file
    disable_ssl_certificate_validation: bool, If true, disable ssl certificate
        validation.
    session: requests.Session instance. Otherwise, a new requests.Session will
        be initialized.
    client_certificate: str, absolute filename of a client_certificate file
    client_key: str, absolute filename of a client_key file

  Returns: A requests.Session subclass.
  c                     sN   d|vr|d< t  r d|vr tt  g| R i ||d<  | i |S )Nr   proxies)_HasBpo42627_AdjustProxiesKwargForBpo42627urllib_requestgetproxies_environmentr7   r8   orig_request_method
proxy_infor   r   r   WrappedRequestz  s   
zSession.<locals>.WrappedRequestF)rL   httpsTNzVUsing provided server certificate %s, client certificate %s, client certificate key %szUsing client certificate %shttps://)r   Sessionrq   r   	trust_envr   !_HasInvalidHttpsProxyEnvVarScheme*_invalid_https_proxy_env_var_warning_shownr	   r   $_INVALID_HTTPS_PROXY_ENV_VAR_WARNINGr   r"   r2   r   Configr   config_type
ConfigTypeENTERPRISE_CERTIFICATEr   ON_DISK_CERTIFICATEencrypted_client_cert_pathencrypted_client_cert_passwordr   mount)
r   r   "disable_ssl_certificate_validationr   r   r   r   r6   adapterr   r   r   r   r   a  s^   





r   c                 C   sZ   | dkr| }nt  }tjjj pd}tjjj	 }|r|}|r#d}t
||||||dS )zECreate a requests.Session matching the appropriate gcloud properties.r   FN)r   r   r   r   r   r   )r   GetDefaultTimeoutr
   rT   authdisable_ssl_validationr^   corecustom_ca_certs_filerW   r   )r   r   r   r   r   effective_timeoutno_validateca_certs_propertyr   r   r   r     s    r   c                 C   sf   t j| }t jj|jdd}t|pi D ]\}}|||< qt|}t jj|dd|d< t j	|S )zFGets the complete URI by merging url and params from the request args.T)keep_blank_values)doseqrG   )
r   rO   r   parse_qsr   six	iteritemslist	urlencoder   )r   params	url_partsquery_paramsparamvaluer   r   r   _GetURIFromRequestArgs  s   
r  c                       s6   e Zd ZdZedd Zd	 fdd	Zdd Z  ZS )
Requesta  Encapsulates parameters for making a general HTTP request.

  This implementation does additional manipulation to ensure that the request
  parameters are specified in the same way as they were specified by the
  caller. That is, if the user calls:
      request('URI', 'GET', None, {'header': '1'})

  After modifying the request, we will call request using positional
  parameters, instead of transforming the request into:
      request('URI', method='GET', body=None, headers={'header': '1'})
  c                 O   s   | |i |S r#   r   )r&   r7   r8   r   r   r   FromRequestArgs  s   zRequest.FromRequestArgsNc                    s.   || _ t||}tt| |||pi | d S r#   )_kwargsr  r$   r  r4   )r5   methodr   r  datar   r8   urir*   r   r   r4     s   
zRequest.__init__c                 C   s8   | j | jg}t| j}| j|d< | jr| j|d< ||fS )Nr   r  )r  r  dictr  r   bodyr<   r   r   r   ToRequestArgs  s   


zRequest.ToRequestArgs)NNN)	r,   r-   r.   r/   classmethodr  r4   r  r0   r   r   r*   r   r    s    
r  c                   @   s   e Zd ZdZedd ZdS )Responsez:Encapsulates responses from making a general HTTP request.c                 C   s   | |j |j|jS r#   )r   r   content)r&   r   r   r   r   FromResponse
  s   zResponse.FromResponseN)r,   r-   r.   r/   r  r  r   r   r   r   r    s    r  c                   @   s    e Zd ZdZeZeZdd ZdS )r   z,Class for wrapping request.Session requests.c                 C   s   ~|S )z&Returns the response without decoding.r   )r5   r   response_encodingr   r   r   DecodeResponse  s   zRequestWrapper.DecodeResponseN)	r,   r-   r.   r/   r  request_classr  response_classr  r   r   r   r   r     s
    r   c               	   C   s^   t  } ttjdttjdd}ttjdd}| jd| dd| di tj| dS )	zGReturns a gcloud's requests session to refresh google-auth credentials.GCE_METADATA_HOSTGCE_METADATA_ROOTzmetadata.google.internalGCE_METADATA_IPz169.254.169.254r   rN   )r   )	r    r   GetEncodedValueosenvironr   updategoogle_auth_requestsr  )r   metadata_rootmetadata_ip_rootr   r   r   GoogleAuthRequest  s$   

r(  c                   @   s   e Zd Zdd Zdd ZdS )_GoogleAuthApitoolsCredentialsc                 C   s
   || _ d S r#   )credentials)r5   r*  r   r   r   r4   ;  s   
z'_GoogleAuthApitoolsCredentials.__init__c                 C   s   ~t  }| j| d S r#   )r(  r*  refresh)r5   r   auth_requestr   r   r   r+  >  s   z&_GoogleAuthApitoolsCredentials.refreshN)r,   r-   r.   r4   r+  r   r   r   r   r)  9  s    r)  c                    sJ   t | ||}t| dr#t| j}|j  fdd}||_t|jd| |S )zGReturns an authenticated httplib2.Http-like object for use by apitools._googlecloudsdk_credentialsc                     s    | i |S r#   r   r   r   r   r   HttpRequestO  s   z(GetApitoolsRequests.<locals>.HttpRequestr*  )_ApitoolsRequestshasattrr)  r-  r   setattr)r   response_handlerr  r   credsr/  r   r.  r   GetApitoolsRequestsD  s   

r5  c                   @   s&   e Zd ZdZdd Zejdd ZdS )ResponseHandlerzHandler to process the Http Response.

  Attributes:
    use_stream: bool, if True, the response body gets returned as a stream
        of data instead of returning the entire body at once.
  c                 C   s
   || _ dS )zInitializes ResponseHandler.

    Args:
      use_stream: bool, if True, the response body gets returned as a stream of
        data instead of returning the entire body at once.
    N)
use_stream)r5   r7  r   r   r   r4   `  s   
zResponseHandler.__init__c                 C   s   dS )zHandles the http response.Nr   )r5   response_streamr   r   r   handlei  s    zResponseHandler.handleN)r,   r-   r.   r/   r4   abcabstractmethodr9  r   r   r   r   r6  X  s
    	r6  c                   @   s6   e Zd ZdZdddZdd Z					dd	d
ZdS )r0  z0A httplib2.Http-like object for use by apitools.Nc                 C   s2   || _ i | _|rt|tstd|| _|| _d S )Nz3response_handler should be of type ResponseHandler.)r   connections
isinstancer6  re   _response_handler_response_encoding)r5   r   r3  r  r   r   r   r4   q  s   

z_ApitoolsRequests.__init__c                 O   sl   ~~|j tjtjfvrtd dS | jjr+tj	j
j r+tj	j
j r+t|j}n|j}| j| dS )z:Response hook to be used if response_handler has been set.z1Skipping response_handler as response is invalid.N)r   httplibOKPARTIAL_CONTENTr	   r   r>  r7  r
   rT   r   log_httpr^   log_http_streaming_bodyioBytesIOr  rawr9  )r5   r   r7   r8   streamr   r   r   ResponseHook|  s   
z_ApitoolsRequests.ResponseHookGETr   c                 C   s   ~|dkr	|| j _i }| jdur| j|d< | jj}nd}| j j||||||d}	t|	j}|	j|d< |r7d}
n| j	durD| j	|	_
|	j}
n|	j}
t||
fS )z/Makes an HTTP request using httplib2 semantics.r   Nr   F)r  r   rH  hooksstatus    )r   max_redirectsr>  rI  r7  r   r  r   r   r?  r   r   r  httplib2r  )r5   r  r  r  r   redirectionsconnection_typerK  r7  r   r  r   r   r   r     s(   






z_ApitoolsRequests.requestNN)rJ  NNr   N)r,   r-   r.   r/   r4   rI  r   r   r   r   r   r0  n  s    
r0  c                  C   s   t  } | dddS )zAReturns whether the HTTPS proxy env var is using an HTTPS scheme.r   rN   r   )r   r   r   
startswith)env_proxiesr   r   r   r     s   r   c                   C   s2   t j t jjkottdot dddS )a  Returns whether Python is affected by https://bugs.python.org/issue42627.

  Due to a bug in Python's standard library, urllib.request misparses the
  Windows registry proxy settings and assumes that HTTPS URLs should use an
  HTTPS proxy, when in fact they should use an HTTP proxy.

  This bug affects PY<3.9, as well as lower patch versions of 3.9, 3.10, and
  3.11.

  Returns:
    True if proxies read from the Windows registry are being parsed incorrectly.
  getproxies_registryr   rN   r   )	r   r   r   WINDOWSr1  r   rU  r   rS  r   r   r   r   r     s   r   c                 O   sf   | s|rdS t j|g|R i |d }tj|}|d}|s#dS |ds*dS d|dddiS )a/  Returns proxies to workaround https://bugs.python.org/issue42627 if needed.

  Args:
    gcloud_proxy_info: str, Proxy info from gcloud properties.
    environment_proxies: dict, Proxy config from http/https_proxy env vars.
    orig_request_method: function, The original requests.Session.request method.
    *args: Positional arguments to the original request method.
    **kwargs: Keyword arguments to the original request method.
  Returns:
    Optional[dict], Adjusted proxies to pass to the request method, or None if
      no adjustment is necessary.
  Nr   r   r   r   r}   )inspectgetcallargsr   utilsget_environ_proxiesr   rS  replace)gcloud_proxy_infoenvironment_proxiesr   r7   r8   r   r   https_proxyr   r   r   r     s   	

r   )r   NNFNNN)NNFNNN)r   NNNNrR  )Nr/   
__future__r   r   r   r:  r   collectionsrW  rE  r   r"  r   r   r   r   r   google.auth.transportr   r%  google.auth.transport.requestsr   googlecloudsdk.corer   r   r	   r
   r   googlecloudsdk.core.utilr   r   r   rO  r  	six.movesr   r@  r   ra   urllib3.util.ssl_r   urllib.requestr   r   ImportErrorr   r   r    
namedtupler"   r1   adaptersr2   rq   r   	Exceptionrr   rv   _EnterpriseCertConfigImplBaseAdapterr   r   r   r   r  r  r  r   r(  r)  r5  with_metaclassABCMetar6  r0  r   r   r   r   r   r   r   <module>   s   

+(,  =
!
]
 
L	