Following CNAMEs

Step 2: Following CNAMEs

A CNAME is an alias: www.example.com β†’ example.com. Resolvers chase the chain until they reach an A record. But a misconfigured zone can loop (a β†’ b β†’ a), so you must detect that and give up.

Refactor into _lookup(name, seen) that returns a list of A values for a name, following CNAMEs, tracking visited names to break loops. resolve(name) returns the first of those values (or None).

Hints
Starter code
import time


class DNSResolver:
    def __init__(self, zone=None, clock=time.time):
        self.zone = zone if zone is not None else {}
        self.clock = clock

    def _lookup(self, name, seen=None):
        """Return the list of A values for name, following CNAMEs; [] if none/loop."""
        seen = seen or set()
        if name in seen:
            return []                      # loop guard
        seen.add(name)
        records = self.zone.get(name, [])
        a_values = [r["value"] for r in records if r["type"] == "A"]
        if a_values:
            return a_values
        # TODO: no A records here, if there's a CNAME, follow it:
        #   for r in records:
        #       if r["type"] == "CNAME":
        #           return self._lookup(r["value"], seen)
        #   return []
        pass

    def resolve(self, name):
        values = self._lookup(name)
        return values[0] if values else None
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.