diff options
-rw-r--r-- | dns/asyncresolver.py | 30 | ||||
-rw-r--r-- | doc/async-resolver-functions.rst | 1 | ||||
-rw-r--r-- | tests/test_async.py | 20 |
3 files changed, 51 insertions, 0 deletions
diff --git a/dns/asyncresolver.py b/dns/asyncresolver.py index 3ac334f..0aaeb9c 100644 --- a/dns/asyncresolver.py +++ b/dns/asyncresolver.py @@ -165,6 +165,28 @@ class Resolver(dns.resolver.Resolver): rdclass=dns.rdataclass.IN, *args, **kwargs) + async def canonical_name(self, name): + """Determine the canonical name of *name*. + + The canonical name is the name the resolver uses for queries + after all CNAME and DNAME renamings have been applied. + + *name*, a ``dns.name.Name`` or ``str``, the query name. + + This method can raise any exception that ``resolve()`` can + raise, other than ``dns.resolver.NoAnswer`` and + ``dns.resolver.NXDOMAIN``. + + Returns a ``dns.name.Name``. + """ + try: + answer = await self.resolve(name, raise_on_no_answer=False) + canonical_name = answer.canonical_name + except dns.resolver.NXDOMAIN as e: + canonical_name = e.canonical_name + return canonical_name + + default_resolver = None @@ -212,6 +234,14 @@ async def resolve_address(ipaddr, *args, **kwargs): return await get_default_resolver().resolve_address(ipaddr, *args, **kwargs) +async def canonical_name(name): + """Determine the canonical name of *name*. + + See ``dns.resolver.Resolver.canonical_name`` for more information on the + parameters and possible exceptions. + """ + + return await get_default_resolver().canonical_name(name) async def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None, backend=None): diff --git a/doc/async-resolver-functions.rst b/doc/async-resolver-functions.rst index fc5798a..b2669f3 100644 --- a/doc/async-resolver-functions.rst +++ b/doc/async-resolver-functions.rst @@ -5,4 +5,5 @@ Asynchronous Resolver Functions .. autofunction:: dns.asyncresolver.resolve .. autofunction:: dns.asyncresolver.resolve_address +.. autofunction:: dns.asyncresolver.canonical_name .. autofunction:: dns.asyncresolver.zone_for_name diff --git a/tests/test_async.py b/tests/test_async.py index db108c8..690a1eb 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -182,6 +182,26 @@ class AsyncTests(unittest.TestCase): dnsgoogle = dns.name.from_text('dns.google.') self.assertEqual(answer[0].target, dnsgoogle) + def testCanonicalNameNoCNAME(self): + cname = dns.name.from_text('www.google.com') + async def run(): + return await dns.asyncresolver.canonical_name('www.google.com') + self.assertEqual(self.async_run(run), cname) + + def testCanonicalNameCNAME(self): + name = dns.name.from_text('www.dnspython.org') + cname = dns.name.from_text('dmfrjf4ips8xa.cloudfront.net') + async def run(): + return await dns.asyncresolver.canonical_name(name) + self.assertEqual(self.async_run(run), cname) + + def testCanonicalNameDangling(self): + name = dns.name.from_text('dangling-cname.dnspython.org') + cname = dns.name.from_text('dangling-target.dnspython.org') + async def run(): + return await dns.asyncresolver.canonical_name(name) + self.assertEqual(self.async_run(run), cname) + def testResolverBadScheme(self): res = dns.asyncresolver.Resolver(configure=False) res.nameservers = ['bogus://dns.google/dns-query'] |