diff --git a/atproto/identity/base_directory.go b/atproto/identity/base_directory.go index 5b509210b..40577eac3 100644 --- a/atproto/identity/base_directory.go +++ b/atproto/identity/base_directory.go @@ -19,6 +19,8 @@ type BaseDirectory struct { Resolver net.Resolver // when doing DNS handle resolution, should this resolver attempt re-try against an authoritative nameserver if the first TXT lookup fails? TryAuthoritativeDNS bool + // set of handle domain suffixes for for which DNS handle resolution will be skipped + SkipDNSDomainSuffixes []string } var _ Directory = (*BaseDirectory)(nil) diff --git a/atproto/identity/handle.go b/atproto/identity/handle.go index 9583cd265..41bb473d2 100644 --- a/atproto/identity/handle.go +++ b/atproto/identity/handle.go @@ -124,24 +124,37 @@ func (d *BaseDirectory) ResolveHandleWellKnown(ctx context.Context, handle synta func (d *BaseDirectory) ResolveHandle(ctx context.Context, handle syntax.Handle) (syntax.DID, error) { // TODO: *could* do resolution in parallel, but expecting that sequential is sufficient to start - start := time.Now() - triedAuthoritative := false - did, dnsErr := d.ResolveHandleDNS(ctx, handle) - if dnsErr == ErrHandleNotFound && d.TryAuthoritativeDNS { - slog.Info("attempting authoritative handle DNS resolution", "handle", handle) - triedAuthoritative = true - // try harder with authoritative lookup - did, dnsErr = d.ResolveHandleDNSAuthoritative(ctx, handle) + var dnsErr error + var did syntax.DID + + tryDNS := true + for _, suffix := range d.SkipDNSDomainSuffixes { + if strings.HasSuffix(handle.String(), suffix) { + tryDNS = false + break + } } - elapsed := time.Since(start) - slog.Debug("resolve handle DNS", "handle", handle, "err", dnsErr, "did", did, "authoritative", triedAuthoritative, "duration_ms", elapsed.Milliseconds()) - if nil == dnsErr { // if *not* an error - return did, nil + + if tryDNS { + start := time.Now() + triedAuthoritative := false + did, dnsErr = d.ResolveHandleDNS(ctx, handle) + if dnsErr == ErrHandleNotFound && d.TryAuthoritativeDNS { + slog.Info("attempting authoritative handle DNS resolution", "handle", handle) + triedAuthoritative = true + // try harder with authoritative lookup + did, dnsErr = d.ResolveHandleDNSAuthoritative(ctx, handle) + } + elapsed := time.Since(start) + slog.Debug("resolve handle DNS", "handle", handle, "err", dnsErr, "did", did, "authoritative", triedAuthoritative, "duration_ms", elapsed.Milliseconds()) + if nil == dnsErr { // if *not* an error + return did, nil + } } - start = time.Now() + start := time.Now() did, httpErr := d.ResolveHandleWellKnown(ctx, handle) - elapsed = time.Since(start) + elapsed := time.Since(start) slog.Debug("resolve handle HTTP well-known", "handle", handle, "err", httpErr, "did", did, "duration_ms", elapsed.Milliseconds()) if nil == httpErr { // if *not* an error return did, nil diff --git a/atproto/identity/identity.go b/atproto/identity/identity.go index bbdb6ff89..1e88e72a1 100644 --- a/atproto/identity/identity.go +++ b/atproto/identity/identity.go @@ -61,6 +61,8 @@ func DefaultDirectory() Directory { }, }, TryAuthoritativeDNS: true, + // primary Bluesky PDS instance only supports HTTP resolution method + SkipDNSDomainSuffixes: []string{".bsky.social"}, } cached := NewCacheDirectory(&base, 10000, time.Hour*24, time.Minute*2) return &cached