checker: build host FQDN from subdomain + apex at service scope

This commit is contained in:
nemunaire 2026-04-29 17:35:31 +07:00
commit 77f8ee4024
5 changed files with 31 additions and 7 deletions

View file

@ -21,6 +21,7 @@ import (
"time" "time"
sdk "git.happydns.org/checker-sdk-go/checker" sdk "git.happydns.org/checker-sdk-go/checker"
happydns "git.happydns.org/happyDomain/model"
"golang.org/x/net/html" "golang.org/x/net/html"
) )
@ -143,7 +144,22 @@ func buildTarget(ctx context.Context, opts sdk.CheckerOptions) (Target, error) {
userAgent = v userAgent = v
} }
host, ips := addressesFromServer(server) // Origin is the FQDN where the service is mounted: svc.Domain holds the
// subdomain (relative to apex; "@" for apex), and the domain_name
// autofill carries the zone apex.
apex := ""
if v, ok := sdk.GetOption[string](opts, OptionDomainName); ok {
apex = strings.TrimSuffix(v, ".")
}
subdomain := ""
if svc, ok := sdk.GetOption[happydns.ServiceMessage](opts, OptionService); ok {
subdomain = strings.TrimSuffix(svc.Domain, ".")
}
origin := sdk.JoinRelative(subdomain, apex)
host, ips := addressesFromServer(server, origin)
if host == "" {
host = origin
}
// abstract.Server only pins one A and one AAAA. Resolve the host to // abstract.Server only pins one A and one AAAA. Resolve the host to
// pick up any additional records the authoritative DNS exposes, so // pick up any additional records the authoritative DNS exposes, so
// multi-IP deployments aren't silently under-probed. Failures are // multi-IP deployments aren't silently under-probed. Failures are

View file

@ -82,6 +82,12 @@ func (p *httpProvider) Definition() *sdk.CheckerDefinition {
AutoFill: sdk.AutoFillService, AutoFill: sdk.AutoFillService,
Hide: true, Hide: true,
}, },
{
Id: OptionDomainName,
Label: "Parent domain name",
AutoFill: sdk.AutoFillDomainName,
Hide: true,
},
}, },
}, },
Rules: Rules(), Rules: Rules(),

View file

@ -227,7 +227,7 @@ func TestAddressesFromServer(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
host, ips := addressesFromServer(c.srv) host, ips := addressesFromServer(c.srv, "")
if host != c.wantHost { if host != c.wantHost {
t.Errorf("host = %q, want %q", host, c.wantHost) t.Errorf("host = %q, want %q", host, c.wantHost)
} }

View file

@ -9,7 +9,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net" "net"
"strings"
sdk "git.happydns.org/checker-sdk-go/checker" sdk "git.happydns.org/checker-sdk-go/checker"
happydns "git.happydns.org/happyDomain/model" happydns "git.happydns.org/happyDomain/model"
@ -36,15 +35,17 @@ func resolveServer(opts sdk.CheckerOptions) (*abstract.Server, error) {
return &server, nil return &server, nil
} }
// addressesFromServer returns the (host, ips) tuple to probe. // addressesFromServer returns the (host, ips) tuple to probe. origin is
func addressesFromServer(server *abstract.Server) (host string, ips []string) { // the service's parent zone; the A/AAAA Hdr.Name is relative to it as
// happyDomain encodes service owners, so we must join before using as FQDN.
func addressesFromServer(server *abstract.Server, origin string) (host string, ips []string) {
if server.A != nil && len(server.A.A) > 0 { if server.A != nil && len(server.A.A) > 0 {
host = strings.TrimSuffix(server.A.Hdr.Name, ".") host = sdk.JoinRelative(server.A.Hdr.Name, origin)
ips = append(ips, server.A.A.String()) ips = append(ips, server.A.A.String())
} }
if server.AAAA != nil && len(server.AAAA.AAAA) > 0 { if server.AAAA != nil && len(server.AAAA.AAAA) > 0 {
if host == "" { if host == "" {
host = strings.TrimSuffix(server.AAAA.Hdr.Name, ".") host = sdk.JoinRelative(server.AAAA.Hdr.Name, origin)
} }
ips = append(ips, server.AAAA.AAAA.String()) ips = append(ips, server.AAAA.AAAA.String())
} }

View file

@ -24,6 +24,7 @@ const ObservationKeyHTTP = "http"
const ( const (
OptionService = "service" OptionService = "service"
OptionDomainName = "domain_name"
OptionProbeTimeoutMs = "probeTimeoutMs" OptionProbeTimeoutMs = "probeTimeoutMs"
OptionMaxRedirects = "maxRedirects" OptionMaxRedirects = "maxRedirects"
OptionUserAgent = "userAgent" OptionUserAgent = "userAgent"