Net.DNS
module Net.DNS
Typed DNS lookup with explicit resolver ownership and bounded caching.
Use DNS.addresses for an occasional hostname lookup. Own a Resolver when a service performs repeated lookups, needs cache statistics, or must query a particular nameserver. Resolver ownership makes both caching and cleanup visible instead of hiding process-wide state behind every lookup.
using Net.DNS
let resolver = Resolver.system.try
let name = Name.parse("example.test").try
let addresses = resolver.addresses(name).try
resolver.close
record Name
A validated DNS name with caller-facing and IDNA ASCII spellings.
display keeps the readable form supplied by the caller; ascii is the wire-safe IDNA form used in DNS queries. Keeping both lets an error message say what the user typed without sending noncanonical labels to a resolver.
Fields
type RecordType
Record families supported by Resolver.lookup.
Variants
AAAAACNAMEMXTXTSRVPTR
type DNSSECStatus
DNSSEC state reported by the underlying resolver. Kex does not independently validate DNSSEC and therefore commonly reports Indeterminate.
Variants
SecureInsecureBogusIndeterminate
type DNSRecord
Typed DNS resource records, preserving MX/SRV priorities and TXT chunks.
Variants
AddressRecord(Net.IP.Address)CanonicalName(Name)MailExchange(Integer, Name)TextRecord([String])ServiceRecord(Integer, Integer, Net.Port, Name)PointerRecord(Name)
record LookupResponse
Records and the reported DNSSEC state from one lookup.
Fields
records[DNSRecord]dnssecDNSSECStatus
record CacheOptions
Bounds for a resolver-owned positive and negative cache.
Positive answers honor their DNS TTL up to maximumTtl. Failed lookups are cached for negativeTtl, preventing a missing hostname from hammering the configured nameserver on every request.
Fields
record Nameserver
One DNS server used by a custom resolver.
Fields
addressNet.IP.AddressportNet.Port
record ResolverOptions
Isolated resolver configuration. An empty search list only queries the name as written; search domains are tried in order for single-label names.
Fields
cacheCacheOptionsoptionalnameservers[Nameserver]search[Name]optionalretriesIntegeroptionaltimeoutDurationoptional
record CacheStatistics
Lifetime cache counters. clear empties entries but keeps these counters.
Compare hits with misses when tuning entries or TTL bounds. A rising evictions count means the resolver is seeing more distinct names than its cache can retain.
Fields
type Resolver
An opaque, process-safe resolver that owns its cache.
Methods
addresses
addresses(name: Name) -> Result<[Net.IP.Address], NetError>
Resolves AAAA and A records, returning IPv6 addresses first.
This is the convenient operation for connecting to a host. Use lookup when record type, TTL-related behavior, or DNSSEC status matters.
Parameters
name- the validated hostname
Returns addresses or Resolve
Examples
Resolving an application upstream
let host = Name.parse("api.example.com").try
let addresses = resolver.addresses(host).try
lookup
lookup(kind: RecordType, name: Name) -> Result<LookupResponse, NetError>
Looks up one supported resource-record family.
Parameters
kind- the requested family
name- the validated owner name
Returns typed records or Resolve
Examples
Discovering a domain's mail exchangers
let response = resolver.lookup(MX, Name.parse("example.com").try).try
response.records.each { |record| IO.inspect(record) }
clear
clear : Void
Empties cached entries without resetting lifetime counters.
Existing statistics remain meaningful across a manual refresh, while the next lookup is forced back to DNS.
Examples
Refreshing service discovery after configuration changes
resolver.clear
statistics
statistics : CacheStatistics
Reports current occupancy and lifetime cache counters.
Returns current entries and lifetime counters
Examples
Reporting whether the cache is doing useful work
let stats = resolver.statistics
IO.printLine("DNS cache: ${stats.hits} hits, ${stats.misses} misses")
close
close : Void
Idempotently closes the resolver.
Calls after closing fail with Closed; closing again is harmless.
module Net.DNS.Name
Validation and IDNA conversion for DNS names.
parse
parse(text: String) -> Result<Name, NetError>
Validates a name and converts Unicode labels to IDNA ASCII.
Parameters
text- a dotted hostname, optionally with a trailing dot
Returns the name, or Parse
Examples
Preparing a user-supplied hostname for lookup
let name = Name.parse("münich.example").try
IO.printLine(name.display)
resolver.addresses(name).try
module Net.DNS.Resolver
Constructors for long-lived, cache-owning resolvers.
system
system(cache: CacheOptions) -> Result<Resolver, NetError>
Opens a resolver using system configuration and default cache bounds.
Reuse the returned resolver for the lifetime of a service so repeated names benefit from its bounded cache, then close it during shutdown.
Returns a resolver handle
Examples
A service-owned resolver
let resolver = Resolver.system.try
let upstream = resolver.addresses(Name.parse("api.example.com").try).try
resolver.close
custom
custom(options: ResolverOptions) -> Result<Resolver, NetError>
Opens an isolated resolver with typed nameservers and query bounds.
This does not inherit the machine's search domains or nameservers. It is useful for tests, service discovery, and applications with their own DNS policy.
Parameters
options- nameservers, search domains, retry count,
Returns a resolver, or Parse
Examples
Querying a DNS server used by a local integration test
let nameserver = Nameserver {
address: Net.IP.Address.parse("127.0.0.1").try,
port: Net.Port.from(5353).try
}
Resolver.custom(ResolverOptions {
nameservers: [nameserver],
timeout: 100.milliseconds
}).try
module Net.DNS.DNS
Convenience lookup operations for callers that do not need resolver ownership or cache reuse.
addresses
addresses(name: Name) -> Result<[Net.IP.Address], NetError>
Resolves a name once with a short-lived system resolver.
Prefer this for command-line tools and one-off checks. A server that looks up names repeatedly should own a Resolver so it can reuse cached answers.
Parameters
name- the validated hostname
Returns addresses or Resolve
Examples
Resolving one host in a short-lived command
let addresses = DNS.addresses(Name.parse("example.com").try).try