Refactor DNS resolution: create an interface to have multiple implementations

This commit is contained in:
nemunaire 2025-11-17 10:15:40 +07:00
commit eef6480e75
2 changed files with 92 additions and 6 deletions

View file

@ -22,7 +22,6 @@
package analyzer
import (
"net"
"time"
"git.happydns.org/happyDeliver/internal/api"
@ -31,19 +30,26 @@ import (
// DNSAnalyzer analyzes DNS records for email domains
type DNSAnalyzer struct {
Timeout time.Duration
resolver *net.Resolver
resolver DNSResolver
}
// NewDNSAnalyzer creates a new DNS analyzer with configurable timeout
func NewDNSAnalyzer(timeout time.Duration) *DNSAnalyzer {
return NewDNSAnalyzerWithResolver(timeout, NewStandardDNSResolver())
}
// NewDNSAnalyzerWithResolver creates a new DNS analyzer with a custom resolver.
// If resolver is nil, a StandardDNSResolver will be used.
func NewDNSAnalyzerWithResolver(timeout time.Duration, resolver DNSResolver) *DNSAnalyzer {
if timeout == 0 {
timeout = 10 * time.Second // Default timeout
}
if resolver == nil {
resolver = NewStandardDNSResolver()
}
return &DNSAnalyzer{
Timeout: timeout,
resolver: &net.Resolver{
PreferGo: true,
},
Timeout: timeout,
resolver: resolver,
}
}

View file

@ -0,0 +1,80 @@
// This file is part of the happyDeliver (R) project.
// Copyright (c) 2025 happyDomain
// Authors: Pierre-Olivier Mercier, et al.
//
// This program is offered under a commercial and under the AGPL license.
// For commercial licensing, contact us at <contact@happydomain.org>.
//
// For AGPL licensing:
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package analyzer
import (
"context"
"net"
)
// DNSResolver defines the interface for DNS resolution operations.
// This interface abstracts DNS lookups to allow for custom implementations,
// such as mock resolvers for testing or caching resolvers for performance.
type DNSResolver interface {
// LookupMX returns the DNS MX records for the given domain.
LookupMX(ctx context.Context, name string) ([]*net.MX, error)
// LookupTXT returns the DNS TXT records for the given domain.
LookupTXT(ctx context.Context, name string) ([]string, error)
// LookupAddr performs a reverse lookup for the given IP address,
// returning a list of hostnames mapping to that address.
LookupAddr(ctx context.Context, addr string) ([]string, error)
// LookupHost looks up the given hostname using the local resolver.
// It returns a slice of that host's addresses (IPv4 and IPv6).
LookupHost(ctx context.Context, host string) ([]string, error)
}
// StandardDNSResolver is the default DNS resolver implementation that uses net.Resolver.
type StandardDNSResolver struct {
resolver *net.Resolver
}
// NewStandardDNSResolver creates a new StandardDNSResolver with default settings.
func NewStandardDNSResolver() DNSResolver {
return &StandardDNSResolver{
resolver: &net.Resolver{
PreferGo: true,
},
}
}
// LookupMX implements DNSResolver.LookupMX using net.Resolver.
func (r *StandardDNSResolver) LookupMX(ctx context.Context, name string) ([]*net.MX, error) {
return r.resolver.LookupMX(ctx, name)
}
// LookupTXT implements DNSResolver.LookupTXT using net.Resolver.
func (r *StandardDNSResolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
return r.resolver.LookupTXT(ctx, name)
}
// LookupAddr implements DNSResolver.LookupAddr using net.Resolver.
func (r *StandardDNSResolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
return r.resolver.LookupAddr(ctx, addr)
}
// LookupHost implements DNSResolver.LookupHost using net.Resolver.
func (r *StandardDNSResolver) LookupHost(ctx context.Context, host string) ([]string, error) {
return r.resolver.LookupHost(ctx, host)
}