The Resolver interface reproduces the standard net.Resolver
but allows us to make a custom implementation on top of any Lookuper.
We provide three mechanisms to create a Resolver:
SystemResolver()/SystemResolverWithDialer()as shortcuts for allocating a standard*net.Resolver{}.NewResolver()returning aResolverusing the givenLookuper{}- and
NewRootResolver()returning aResolverusing iterative lookup.
The Lookuper interface is centred on Resolver, making simple INET queries.
type Lookuper interface {
Lookup(ctx context.Context, qName string, qType uint16) (*dns.Msg, error)
}
type LookuperFunc func(ctx context.Context, qName string, qType uint16) (*dns.Msg, error)Additionally we can use any function implementing the same signature as LookuperFunc,
which returns a type implementing Lookuper and Exchanger using the given function.
The Exchanger interface is an alternative to Lookuper but taking pre-assembled
*dns.Msg{} queries.
type Exchanger interface {
Exchange(ctx context.Context, msg *dns.Msg) (*dns.Msg, error)
}
type ExchangerFunc func(ctx context.Context, msg *dns.Msg) (*dns.Msg, error)Additionally we can use any function implementing the same signature as ExchangerFunc,
which returns a type implementing Lookuper and Exchanger using the
given function.
The client.Client interface represents ExchangeContext() of *dns.Client to perform a *dns.Msg{} against the specified server.
type Client interface {
ExchangeContext(ctx context.Context, req *dns.Msg, server string) (*dns.Msg, time.Duration, error)
}
type ExchangeFunc func(ctx context.Context, req *dns.Msg, server string) (*dns.Msg, time.Duration, error)
type Unwrapper interface {
Unwrap() *dns.Client
}Additionally we can use any function implementing the same signature as client.ExchangeFunc, which returns a type implementing client.Client using the given functions.
Clients are advised to also implement Unwrapper to access the underlying *dns.Client{}.
We use the standard *net.DNSError{} for all our errors, but also provide errors.MsgAsError() and errors.ErrorAsMsg() to convert back and forth between the errors we emit and an equivalent *dns.Msg.
server.Handler implements a dns.Handler on top of a Lookuper or Exchanger.
client.NewDefaultClient() can be used to get a plain UDP *dns.Client{} with an optional message size.
The client.Auto Client distinguishes requests by server protocol and retries truncated UDP requests as TCP.
client.Auto uses udp://, tcp:// and tls:// server prefixes for protocol specific and uses UDP followed by a TCP retry if no prefix is specified.
client.NoAAAA is a Client Middleware that removes all AAAA entries, to be used on systems were IPv6 isn't fully functional.
client.SingleFlight is a Client Middleware that implements a barrier to catch identical queries, with a small caching period. Only the req.Id is ignored when comparing requests, and it operates per-server.
client.WorkerPool is a Client Middleware that implements a barrier limiting
the number of exchange calls that can happen in parallel. It's ideally
use behind a SingleFlight Client.
reflect.Client implements logging middleware if front of a client.Client.
The RootLookuper implements an iterative Lookuper/Exchanger, supporting an optional custom client.Client.
SingleLookuper implements a forwarding Lookuper/Exchanger passing requests as-is to a client.Client.
MultiLookuper implements a parallel Lookuper/Exchanger that will pass the request to multiple Lookuper/Exchanger instances and return the first response.
SingleFlight implements a Lookuper/Exchanger barrier to hold identical requests at
the same time, before passing them over to another.
reflect.Lookuper implements logging middleware in front of a Lookuper or Exchanger.
For convenience we provide shortcuts to create forwarding Lookupers to well known recursive resolvers.
NewGoogleLookuper()using8.8.8.8,NewGoogleLookuper2()using8.8.4.4,NewCloudflareLookuper()using1.1.1.1,NewQuad9Lookuper()using9.9.9.9,- and
NewQuad9Lookuper6()using Quad9's2620:fe::f3.
reflect.Lookuper and reflect.Client allow us to hook a dynamically enabled logging layer with an optional tracing ID, using the darvaza.org/slog.Logger interface.