Vasiliy Tolstov bf4143cde5 replace default go resolver with caching resolver
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-03 01:11:08 +03:00

78 lines
1.5 KiB
Go

// Package dns resolves names to dns records
package dns
import (
"context"
"net"
"sync"
"time"
"go.unistack.org/micro/v3/resolver"
)
// Resolver is a DNS network resolve
type Resolver struct {
goresolver *net.Resolver
Address string
mu sync.RWMutex
}
// Resolve tries to resolve endpoint address
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
host, port, err := net.SplitHostPort(name)
if err != nil {
host = name
port = "8085"
}
if len(host) == 0 {
host = "localhost"
}
if len(r.Address) == 0 {
r.Address = "1.1.1.1:53"
}
// parsed an actual ip
if v := net.ParseIP(host); v != nil {
rec := &resolver.Record{Address: net.JoinHostPort(host, port)}
return []*resolver.Record{rec}, nil
}
r.mu.RLock()
goresolver := r.goresolver
r.mu.RUnlock()
if goresolver == nil {
r.mu.Lock()
r.goresolver = &net.Resolver{
Dial: func(ctx context.Context, _ string, _ string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Millisecond * time.Duration(100),
}
return d.DialContext(ctx, "udp", r.Address)
},
}
r.mu.Unlock()
}
addrs, err := goresolver.LookupIP(context.TODO(), "ip", host)
if err != nil {
return nil, err
}
if len(addrs) == 0 {
rec := &resolver.Record{Address: net.JoinHostPort(host, port)}
return []*resolver.Record{rec}, nil
}
records := make([]*resolver.Record, 0, len(addrs))
for _, addr := range addrs {
records = append(records, &resolver.Record{
Address: net.JoinHostPort(addr.String(), port),
})
}
return records, nil
}