return (af, destination, source)
-def https(q, where, timeout=None, port=443, path='/dns-query', post=True,
+def https(q, where, session, timeout=None, port=443, path='/dns-query', post=True,
verify=True, source=None, source_port=0,
one_rr_per_rrset=False, ignore_trailing=False):
"""Return the response obtained after sending a query via DNS-over-HTTPS.
address is given, the URL will be constructed using the following schema:
https:<IP-address>:<port>/<path>.
+ *session*, a ``requests.session.Session``, the session to use to send the
+ queries. This argument is required to allow for connection reuse.
+
*timeout*, a ``float`` or ``None``, the number of seconds to
wait before the query times out. If ``None``, the default, wait forever.
url = 'https://{}:{}{}'.format(where, port, path)
except ValueError:
url = where
- session = requests.sessions.Session()
+ # session = requests.sessions.Session()
try:
# set source port and source address
# see https://github.com/requests/toolbelt/blob/master/requests_toolbelt/adapters/source.py
- session.mount('http://', SourceAddressAdapter(source))
- session.mount('https://', SourceAddressAdapter(source))
+ session.mount(url, SourceAddressAdapter(source))
# see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH GET and POST examples
if post:
from typing import Optional, Union, Dict, Generator, Any
from . import tsig, rdatatype, rdataclass, name, message
+from requests.sessions import Session
try:
import ssl
class ssl(object):
SSLContext = {}
-def https(q : message.Message, where: str, timeout : Optional[float] = None, port : Optional[int] = 443, path : Optional[str] = '/dns-query', post : Optional[bool] = True,
+def https(q : message.Message, where: str, session: Session, timeout : Optional[float] = None, port : Optional[int] = 443, path : Optional[str] = '/dns-query', post : Optional[bool] = True,
verify : Optional[bool] = True, source : Optional[str] = None, source_port : Optional[int] = 0,
one_rr_per_rrset : Optional[bool] = False, ignore_trailing : Optional[bool] = False) -> message.Message:
pass
import unittest
import random
+import requests
+
import dns.query
import dns.rdatatype
import dns.message
'https://dns11.quad9.net/dns-query']
class DNSOverHTTPSTestCase(unittest.TestCase):
- nameserver_ip = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_IPS)
+ def setUp(self):
+ self.session = requests.sessions.Session()
+
+ def tearDown(self):
+ self.session.close()
def test_get_request(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, post=False)
+ r = dns.query.https(q, nameserver_url, self.session, post=False)
self.assertTrue(q.is_response(r))
def test_post_request(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, post=True)
+ r = dns.query.https(q, nameserver_url, self.session, post=True)
self.assertTrue(q.is_response(r))
def test_build_url_from_ip(self):
q = dns.message.make_query('example.com.', dns.rdatatype.A)
# For some reason Google's DNS over HTTPS fails when you POST to https://8.8.8.8/dns-query
# So we're just going to do GET requests here
- r = dns.query.https(q, nameserver_ip, post=False)
+ r = dns.query.https(q, nameserver_ip, self.session, post=False)
self.assertTrue(q.is_response(r))
if __name__ == '__main__':