1# -*- coding: utf-8 -*- #
2# Copyright 2013 Google LLC. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#    http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""A module to get an http proxy information."""
17
18
19from __future__ import absolute_import
20from __future__ import division
21from __future__ import unicode_literals
22
23from googlecloudsdk.core import properties
24from googlecloudsdk.core.util import http_proxy_types
25
26import httplib2
27from six.moves import urllib
28
29
30def GetDefaultProxyInfo(method='http'):
31  """Get ProxyInfo from environment.
32
33  This function is meant to mimic httplib2.proxy_info_from_environment, but get
34  the proxy information from urllib.getproxies instead. urllib can also get
35  proxy information from Windows Internet Explorer settings or MacOSX framework
36  SystemConfiguration.
37
38  Args:
39    method: protocol string
40  Returns:
41    httplib2 ProxyInfo object or None
42  """
43
44  proxy_dict = urllib.request.getproxies()
45  proxy_url = proxy_dict.get(method, None)
46  if not proxy_url:
47    return None
48
49  pi = httplib2.proxy_info_from_url(proxy_url, method)
50
51  # The ProxyInfo object has a bypass_host method that takes the hostname as an
52  # argument and it returns 1 or 0 based on if the hostname should bypass the
53  # proxy or not. We could either build the bypassed hosts list and pass it to
54  # pi.bypass_hosts, or we can just replace the method with the function in
55  # urllib, and completely mimic urllib logic. We do the latter.
56  # Since the urllib.proxy_bypass _function_ (no self arg) is not "bound" to the
57  # class instance, it doesn't receive the self arg when its called. We don't
58  # need to "bind" it via types.MethodType(urllib.proxy_bypass, pi).
59  pi.bypass_host = urllib.request.proxy_bypass
60
61  # Modify proxy info object?
62
63  return pi
64
65
66def GetProxyProperties():
67  """Get proxy information from cloud sdk properties in dictionary form."""
68  proxy_type_map = http_proxy_types.PROXY_TYPE_MAP
69  proxy_type = properties.VALUES.proxy.proxy_type.Get()
70  proxy_address = properties.VALUES.proxy.address.Get()
71  proxy_port = properties.VALUES.proxy.port.GetInt()
72
73  proxy_prop_set = len(
74      [f for f in (proxy_type, proxy_address, proxy_port) if f])
75  if proxy_prop_set > 0 and proxy_prop_set != 3:
76    raise properties.InvalidValueError(
77        'Please set all or none of the following properties: '
78        'proxy/type, proxy/address and proxy/port')
79
80  if not proxy_prop_set:
81    return {}
82
83  proxy_rdns = properties.VALUES.proxy.rdns.GetBool()
84  proxy_user = properties.VALUES.proxy.username.Get()
85  proxy_pass = properties.VALUES.proxy.password.Get()
86
87  return {
88      'proxy_type': proxy_type_map[proxy_type],
89      'proxy_address': proxy_address,
90      'proxy_port': proxy_port,
91      'proxy_rdns': proxy_rdns,
92      'proxy_user': proxy_user,
93      'proxy_pass': proxy_pass,
94  }
95
96
97def GetHttpProxyInfo():
98  """Get ProxyInfo object or callable to be passed to httplib2.Http.
99
100  httplib2.Http can issue requests through a proxy. That information is passed
101  via either ProxyInfo objects or a callback function that receives the protocol
102  the request is made on and returns the proxy address. If users set the gcloud
103  properties, we create a ProxyInfo object with those settings. If users do not
104  set gcloud properties, we return a function that can be called to get default
105  settings.
106
107  Returns:
108    httplib2 ProxyInfo object or callable function that returns a Proxy Info
109    object given the protocol (http, https)
110  """
111
112  proxy_settings = GetProxyProperties()
113
114  if proxy_settings:
115    return httplib2.ProxyInfo(
116        proxy_settings['proxy_type'],
117        proxy_settings['proxy_address'],
118        proxy_settings['proxy_port'],
119        proxy_rdns=proxy_settings['proxy_rdns'],
120        proxy_user=proxy_settings['proxy_user'],
121        proxy_pass=proxy_settings['proxy_pass'])
122
123  return GetDefaultProxyInfo
124