mirror of
https://github.com/kennethreitz/requests.git
synced 2026-06-05 14:50:16 +00:00
New helper method set_http_proxy in Session to set proxies in a more user friendly way
This commit is contained in:
@@ -698,6 +698,91 @@ class Session(SessionRedirectMixin):
|
||||
|
||||
return r
|
||||
|
||||
def set_http_proxy(self,
|
||||
http_scheme='http', # type: str
|
||||
http_host=None, # type: str
|
||||
http_port=80, # type: int
|
||||
http_url=None, # type: str
|
||||
use_http_proxy_for_https_requests=False, # type: bool
|
||||
https_scheme='https', # type: str
|
||||
https_host=None, # type: str
|
||||
https_port=443, # type: int
|
||||
https_url=None, # type: str
|
||||
replace=False # type: bool
|
||||
):
|
||||
"""Update or replace self.proxies with the provided proxy information.
|
||||
|
||||
This method updates or replaces (depending on the value of `replace`) the dictionary in `self.proxies` with the
|
||||
provided information. For each kind of connection (http and https), there are two ways to pass the information:
|
||||
either as an url string (`http_url`, `https_url`), or split in schema/host/port, with sensible defaults.
|
||||
In addition if the exact same proxy information is to be used for http and https, you can pass only the http
|
||||
one and set `use_http_proxy_for_https_requests` to True.
|
||||
|
||||
See :ref:`Proxies documentation <_proxies>` for details.
|
||||
|
||||
:param http_host: (optional) a string indicating the http proxy host, for example '10.10.1.10' or 'acme.com'.
|
||||
:param http_port: (optional) an int indicating the http proxy port, for example `3128`.
|
||||
:param http_scheme: (optional) a string indicating the scheme to use for http proxy. By default this is 'http'
|
||||
but you can consider using 'socks5', 'socks5h'. See documentation for details.
|
||||
:param http_url: (optional) a string indicating the full http proxy url. For example 'http://10.10.1.10:3128'
|
||||
or 'http://user:pass@10.10.1.10:3128/' or 'socks5://user:pass@host:port'.
|
||||
Only one of {http_scheme + http_host + http_port} or {http_url} should be provided.
|
||||
:param use_http_proxy_for_https_requests: (optional) a boolean indicating whether the information provided for
|
||||
the http proxy should be copied for the https proxy. Note that the full url will be copied including the
|
||||
scheme (so by default 'http').
|
||||
:param https_host: (optional) a string indicating the https proxy host, for example '10.10.1.10' or 'acme.com'.
|
||||
:param https_port: (optional) an int indicating the https proxy port, for example `3128`.
|
||||
:param https_scheme: (optional) a string indicating the scheme to use for https proxy. By default this is
|
||||
'https' but you can consider using 'socks5', 'socks5h'. See documentation for details.
|
||||
:param https_url: (optional) a string indicating the full https proxy url. For example 'https://10.10.1.10:3128'
|
||||
or 'http://user:pass@10.10.1.10:3128/' or 'socks5://user:pass@host:port'.
|
||||
Only one of {https_scheme + https_host + https_port} or {https_url} should be provided.
|
||||
:param replace: (optional) a boolean indicating if the provided information should replace the existing one
|
||||
(True) or just update it (False, default).
|
||||
:return:
|
||||
"""
|
||||
proxies = dict()
|
||||
|
||||
# HTTPS
|
||||
if http_host is not None:
|
||||
# (a) scheme + host + port
|
||||
if http_url is not None:
|
||||
raise ValueError("Only one of `http_host` and `http_url` should be provided")
|
||||
proxies['http'] = "%s://%s:%s" % (http_scheme, http_host, http_port)
|
||||
elif http_url is not None:
|
||||
# (b) full url
|
||||
proxies['http'] = http_url
|
||||
elif http_port != 80 or http_scheme != 'http':
|
||||
raise ValueError("An `http_host` should be provided if you wish to change `http_port` or `http_scheme`")
|
||||
|
||||
# HTTPS
|
||||
if use_http_proxy_for_https_requests:
|
||||
# (a) copy the information from http
|
||||
if https_host is not None or https_url is not None or https_port != 443 or https_scheme != "https":
|
||||
raise ValueError("`use_http_proxy_for_https_requests` was set to `True` but custom information for "
|
||||
"https was provided.")
|
||||
try:
|
||||
proxies['https'] = proxies['http']
|
||||
except KeyError:
|
||||
raise ValueError("`use_http_proxy_for_https_requests` was set to `True` but no information was "
|
||||
"provided for the http proxy")
|
||||
elif https_host is not None:
|
||||
# (b) scheme + host + port
|
||||
if https_url is not None:
|
||||
raise ValueError("Only one of `https_host` and `https_url` should be provided")
|
||||
proxies['https'] = '%s://%s:%s' % (https_scheme, https_host, https_port)
|
||||
elif https_url is not None:
|
||||
# (c) full url
|
||||
proxies['https'] = https_url
|
||||
elif https_port != 443 or https_scheme != 'https':
|
||||
raise ValueError("An `https_host` should be provided if you wish to change `https_port` or `https_scheme`")
|
||||
|
||||
# Replace or update (default) the configuration
|
||||
if replace:
|
||||
self.proxies = proxies
|
||||
else:
|
||||
self.proxies.update(proxies)
|
||||
|
||||
def merge_environment_settings(self, url, proxies, stream, verify, cert):
|
||||
"""
|
||||
Check the environment and merge it with some settings.
|
||||
|
||||
@@ -151,6 +151,41 @@ class TestRequests:
|
||||
request = requests.Request('GET', ' http://example.com').prepare()
|
||||
assert request.url == 'http://example.com/'
|
||||
|
||||
def test_proxies_shortcut(self):
|
||||
"""Test that the set_http_proxy helper function works correctly"""
|
||||
s = requests.Session()
|
||||
|
||||
# nominal
|
||||
s.set_http_proxy(http_scheme='socks5', http_host='acme.com', http_port=999)
|
||||
assert s.proxies == {'http': 'socks5://acme.com:999'}
|
||||
s.set_http_proxy(https_scheme='socks5h', https_host='acme.org', https_port=80)
|
||||
assert s.proxies == {'http': 'socks5://acme.com:999', 'https': 'socks5h://acme.org:80'}
|
||||
|
||||
# one can not specify a scheme or a port without passing a host
|
||||
with pytest.raises(ValueError):
|
||||
s.set_http_proxy(http_scheme='socks5')
|
||||
with pytest.raises(ValueError):
|
||||
s.set_http_proxy(https_scheme='socks5')
|
||||
with pytest.raises(ValueError):
|
||||
s.set_http_proxy(http_port=999)
|
||||
with pytest.raises(ValueError):
|
||||
s.set_http_proxy(https_port=999)
|
||||
|
||||
# use_http_proxy_for_https_requests requires http related information to be present
|
||||
with pytest.raises(ValueError):
|
||||
s.set_http_proxy(use_http_proxy_for_https_requests=True)
|
||||
|
||||
# reuse http info for https
|
||||
s.set_http_proxy(http_url='http://10.10.10.10:80', use_http_proxy_for_https_requests=True)
|
||||
assert s.proxies == {'http': 'http://10.10.10.10:80', 'https': 'http://10.10.10.10:80'}
|
||||
|
||||
# replace instead of update
|
||||
s.set_http_proxy(https_url='http://10.10.10.20:80', replace=True)
|
||||
assert s.proxies == {'https': 'http://10.10.10.20:80'}
|
||||
|
||||
# https url
|
||||
s.set_http_proxy(https_url='http://10.10.10.20:80', replace=True)
|
||||
|
||||
@pytest.mark.parametrize('scheme', ('http://', 'HTTP://', 'hTTp://', 'HttP://'))
|
||||
def test_mixed_case_scheme_acceptable(self, httpbin, scheme):
|
||||
s = requests.Session()
|
||||
|
||||
Reference in New Issue
Block a user