From ea9b29fb1d1b7d764561621261381f544fa6fd41 Mon Sep 17 00:00:00 2001 From: Daniel Lenski Date: Thu, 30 Apr 2020 17:31:28 -0700 Subject: [PATCH] make DOH an extra feature (to avoid requests as hard dependency) --- dns/query.py | 21 ++++++++++++++++++--- doc/exceptions.rst | 1 + setup.py | 2 +- tests/test_doh.py | 2 ++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/dns/query.py b/dns/query.py index 725eff19..174a7fb7 100644 --- a/dns/query.py +++ b/dns/query.py @@ -38,9 +38,14 @@ import dns.rcode import dns.rdataclass import dns.rdatatype -import requests -from requests_toolbelt.adapters.source import SourceAddressAdapter -from requests_toolbelt.adapters.host_header_ssl import HostHeaderSSLAdapter +try: + import requests + from requests_toolbelt.adapters.source import SourceAddressAdapter + from requests_toolbelt.adapters.host_header_ssl import HostHeaderSSLAdapter + have_doh = True +except ImportError: + have_doh = False + try: import ssl @@ -76,6 +81,11 @@ class TransferError(dns.exception.DNSException): self.rcode = rcode +class NoDOH(dns.exception.DNSException): + """DNS over HTTPS (DOH) was requested but the requests module is not + available.""" + + def _compute_expiration(timeout): if timeout is None: return None @@ -226,6 +236,8 @@ def send_https(session, what, lifetime=None): :param lifetime: timeout (in seconds) :return: a :class:`requests.models.Response` object. """ + if not have_doh: + raise NoDOH if isinstance(what, requests.models.Request): what = what.prepare() return session.send(what, timeout=lifetime) @@ -280,6 +292,9 @@ def https(q, where, timeout=None, port=443, af=None, source=None, source_port=0, Returns a ``dns.message.Message``. """ + if not have_doh: + raise NoDOH + wire = q.to_wire() (af, destination, source) = _destination_and_source(af, where, port, source, source_port, diff --git a/doc/exceptions.rst b/doc/exceptions.rst index b7054822..b227e15f 100644 --- a/doc/exceptions.rst +++ b/doc/exceptions.rst @@ -50,6 +50,7 @@ dns.query Exceptions -------------------- .. autoexception:: dns.query.BadResponse +.. autoexception:: dns.query.NoDOH .. autoexception:: dns.query.UnexpectedSource .. autoexception:: dns.query.TransferError diff --git a/setup.py b/setup.py index 16fe7560..6e0c945a 100755 --- a/setup.py +++ b/setup.py @@ -71,9 +71,9 @@ direct manipulation of DNS zones, messages, names, and records.""", 'python_requires': '>=3.4', 'test_suite': 'tests', 'provides': ['dns'], - 'install_requires': ['requests', 'requests-toolbelt'], 'tests_require': ['typing ; python_version<"3.5"'], 'extras_require': { + 'DOH': ['requests', 'requests-toolbelt'], 'IDNA': ['idna>=2.1'], 'DNSSEC': ['cryptography>=2.6'], }, diff --git a/tests/test_doh.py b/tests/test_doh.py index 41d8331c..2e16aa23 100644 --- a/tests/test_doh.py +++ b/tests/test_doh.py @@ -30,6 +30,8 @@ KNOWN_ANYCAST_DOH_RESOLVER_URLS = ['https://cloudflare-dns.com/dns-query', 'https://dns.google/dns-query', 'https://dns11.quad9.net/dns-query'] +@unittest.skipUnless(dns.query.have_doh, + "Python requests cannot be imported; no DNS over HTTPS (DOH)") class DNSOverHTTPSTestCase(unittest.TestCase): def setUp(self): self.session = requests.sessions.Session() -- 2.47.3