requests
uses urllib3
, which ultimately uses httplib.HTTPConnection
as well, so the techniques from https://stackoverflow.com/questions/4623090/python-set-custom-dns-server-for-urllib-requests (now deleted, it merely linked to Tell urllib2 to use custom DNS) still apply, to a certain extent.
The urllib3.connection
module subclasses httplib.HTTPConnection
under the same name, having replaced the .connect()
method with one that calls self._new_conn
. In turn, this delegates to urllib3.util.connection.create_connection()
. It is perhaps easiest to patch that function:
from urllib3.util import connection
_orig_create_connection = connection.create_connection
def patched_create_connection(address, *args, **kwargs):
"""Wrap urllib3's create_connection to resolve the name elsewhere"""
# resolve hostname to an ip address; use your own
# resolver here, as otherwise the system resolver will be used.
host, port = address
hostname = your_dns_resolver(host)
return _orig_create_connection((hostname, port), *args, **kwargs)
connection.create_connection = patched_create_connection
and you'd provide your own code to resolve the host
portion of the address into an ip address instead of relying on the connection.create_connection()
call (which wraps socket.create_connection()
) to resolve the hostname for you.
Like all monkeypatching, be careful that the code hasn't significantly changed in later releases; the patch here was created against urllib3
version 1.21.1. but should work for versions as far back as 1.9.
Note that this answer was re-written to work with newer urllib3
releases, which have added a much more convenient patching location. See the edit history for the old method, applicable to version < 1.9, as a patch to the vendored urllib3
version rather than a stand-alone installation.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…