import requests
def select_proxy(url, proxies):
"""Select a proxy for the url, if applicable.
:param url: The url being for the request
:param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
"""
proxies = proxies or {}
urlparts = requests.utils.urlparse(url)
if urlparts.hostname is None:
return proxies.get(urlparts.scheme, proxies.get('all'))
proxy = None
if requests.utils.should_bypass_proxies(url, proxies.get('no_proxy')):
return proxy
proxy_keys = [
urlparts.scheme + '://' + urlparts.hostname,
urlparts.scheme,
'all://' + urlparts.hostname,
'all',
]
for proxy_key in proxy_keys:
if proxy_key in proxies:
proxy = proxies[proxy_key]
break
return proxy
class NoProxyAdapter(requests.adapters.HTTPAdapter):
def get_connection(self, url, proxies=None):
"""Returns a urllib3 connection for the given URL. This should not be
called from user code, and is only exposed for use when subclassing the
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
:param url: The URL to connect to.
:param proxies: (optional) A Requests-style dictionary of proxies used on this request.
:rtype: urllib3.ConnectionPool
"""
proxy = select_proxy(url, proxies)
if proxy and proxy not in proxies.get('no_proxy', []):
proxy = requests.adapters.prepend_scheme_if_needed(proxy, 'http')
proxy_manager = self.proxy_manager_for(proxy)
conn = proxy_manager.connection_from_url(url)
else:
# Only scheme should be lower case
parsed = requests.adapters.urlparse(url)
url = parsed.geturl()
conn = self.poolmanager.connection_from_url(url)
return conn
if __name__ == "__main__":
s = requests.Session()
s.mount('http://', NoProxyAdapter())
r = requests.Request(url='http://127.0.0.2').prepare()
s.send(
r,
proxies={
'http': 'http://127.0.0.1:8090',
'no_proxy': '127.0.0.2',
},
)
aW1wb3J0IHJlcXVlc3RzCgoKZGVmIHNlbGVjdF9wcm94eSh1cmwsIHByb3hpZXMpOgogICAgIiIiU2VsZWN0IGEgcHJveHkgZm9yIHRoZSB1cmwsIGlmIGFwcGxpY2FibGUuCgogICAgOnBhcmFtIHVybDogVGhlIHVybCBiZWluZyBmb3IgdGhlIHJlcXVlc3QKICAgIDpwYXJhbSBwcm94aWVzOiBBIGRpY3Rpb25hcnkgb2Ygc2NoZW1lcyBvciBzY2hlbWVzIGFuZCBob3N0cyB0byBwcm94eSBVUkxzCiAgICAiIiIKICAgIHByb3hpZXMgPSBwcm94aWVzIG9yIHt9CiAgICB1cmxwYXJ0cyA9IHJlcXVlc3RzLnV0aWxzLnVybHBhcnNlKHVybCkKICAgIGlmIHVybHBhcnRzLmhvc3RuYW1lIGlzIE5vbmU6CiAgICAgICAgcmV0dXJuIHByb3hpZXMuZ2V0KHVybHBhcnRzLnNjaGVtZSwgcHJveGllcy5nZXQoJ2FsbCcpKQoKICAgIHByb3h5ID0gTm9uZQogICAgaWYgcmVxdWVzdHMudXRpbHMuc2hvdWxkX2J5cGFzc19wcm94aWVzKHVybCwgcHJveGllcy5nZXQoJ25vX3Byb3h5JykpOgogICAgICAgIHJldHVybiBwcm94eQoKICAgIHByb3h5X2tleXMgPSBbCiAgICAgICAgdXJscGFydHMuc2NoZW1lICsgJzovLycgKyB1cmxwYXJ0cy5ob3N0bmFtZSwKICAgICAgICB1cmxwYXJ0cy5zY2hlbWUsCiAgICAgICAgJ2FsbDovLycgKyB1cmxwYXJ0cy5ob3N0bmFtZSwKICAgICAgICAnYWxsJywKICAgIF0KCiAgICBmb3IgcHJveHlfa2V5IGluIHByb3h5X2tleXM6CiAgICAgICAgaWYgcHJveHlfa2V5IGluIHByb3hpZXM6CiAgICAgICAgICAgIHByb3h5ID0gcHJveGllc1twcm94eV9rZXldCiAgICAgICAgICAgIGJyZWFrCgogICAgcmV0dXJuIHByb3h5CgoKY2xhc3MgTm9Qcm94eUFkYXB0ZXIocmVxdWVzdHMuYWRhcHRlcnMuSFRUUEFkYXB0ZXIpOgogICAgZGVmIGdldF9jb25uZWN0aW9uKHNlbGYsIHVybCwgcHJveGllcz1Ob25lKToKICAgICAgICAiIiJSZXR1cm5zIGEgdXJsbGliMyBjb25uZWN0aW9uIGZvciB0aGUgZ2l2ZW4gVVJMLiBUaGlzIHNob3VsZCBub3QgYmUKICAgICAgICBjYWxsZWQgZnJvbSB1c2VyIGNvZGUsIGFuZCBpcyBvbmx5IGV4cG9zZWQgZm9yIHVzZSB3aGVuIHN1YmNsYXNzaW5nIHRoZQogICAgICAgIDpjbGFzczpgSFRUUEFkYXB0ZXIgPHJlcXVlc3RzLmFkYXB0ZXJzLkhUVFBBZGFwdGVyPmAuCgogICAgICAgIDpwYXJhbSB1cmw6IFRoZSBVUkwgdG8gY29ubmVjdCB0by4KICAgICAgICA6cGFyYW0gcHJveGllczogKG9wdGlvbmFsKSBBIFJlcXVlc3RzLXN0eWxlIGRpY3Rpb25hcnkgb2YgcHJveGllcyB1c2VkIG9uIHRoaXMgcmVxdWVzdC4KICAgICAgICA6cnR5cGU6IHVybGxpYjMuQ29ubmVjdGlvblBvb2wKICAgICAgICAiIiIKICAgICAgICBwcm94eSA9IHNlbGVjdF9wcm94eSh1cmwsIHByb3hpZXMpCgogICAgICAgIGlmIHByb3h5IGFuZCBwcm94eSBub3QgaW4gcHJveGllcy5nZXQoJ25vX3Byb3h5JywgW10pOgogICAgICAgICAgICBwcm94eSA9IHJlcXVlc3RzLmFkYXB0ZXJzLnByZXBlbmRfc2NoZW1lX2lmX25lZWRlZChwcm94eSwgJ2h0dHAnKQogICAgICAgICAgICBwcm94eV9tYW5hZ2VyID0gc2VsZi5wcm94eV9tYW5hZ2VyX2Zvcihwcm94eSkKICAgICAgICAgICAgY29ubiA9IHByb3h5X21hbmFnZXIuY29ubmVjdGlvbl9mcm9tX3VybCh1cmwpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgIyBPbmx5IHNjaGVtZSBzaG91bGQgYmUgbG93ZXIgY2FzZQogICAgICAgICAgICBwYXJzZWQgPSByZXF1ZXN0cy5hZGFwdGVycy51cmxwYXJzZSh1cmwpCiAgICAgICAgICAgIHVybCA9IHBhcnNlZC5nZXR1cmwoKQogICAgICAgICAgICBjb25uID0gc2VsZi5wb29sbWFuYWdlci5jb25uZWN0aW9uX2Zyb21fdXJsKHVybCkKCiAgICAgICAgcmV0dXJuIGNvbm4KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgcyA9IHJlcXVlc3RzLlNlc3Npb24oKQogICAgcy5tb3VudCgnaHR0cDovLycsIE5vUHJveHlBZGFwdGVyKCkpCiAgICByID0gcmVxdWVzdHMuUmVxdWVzdCh1cmw9J2h0dHA6Ly8xMjcuMC4wLjInKS5wcmVwYXJlKCkKICAgIHMuc2VuZCgKICAgICAgICByLAogICAgICAgIHByb3hpZXM9ewogICAgICAgICAgICAnaHR0cCc6ICdodHRwOi8vMTI3LjAuMC4xOjgwOTAnLAogICAgICAgICAgICAnbm9fcHJveHknOiAnMTI3LjAuMC4yJywKICAgICAgICB9LAogICAgKQo=