-
Notifications
You must be signed in to change notification settings - Fork 85
/
base_directory.go
103 lines (93 loc) · 3.17 KB
/
base_directory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package identity
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"github.com/bluesky-social/indigo/atproto/syntax"
"golang.org/x/time/rate"
)
// The zero value ('BaseDirectory{}') is a usable Directory.
type BaseDirectory struct {
// if non-empty, this string should have URL method, hostname, and optional port; it should not have a path or trailing slash
PLCURL string
// If not nil, this limiter will be used to rate-limit requests to the PLCURL
PLCLimiter *rate.Limiter
// If not nil, this function will be called inline with DID Web lookups, and can be used to limit the number of requests to a given hostname
DIDWebLimitFunc func(ctx context.Context, hostname string) error
// HTTP client used for did:web, did:plc, and HTTP (well-known) handle resolution
HTTPClient http.Client
// DNS resolver used for DNS handle resolution. Calling code can use a custom Dialer to query against a specific DNS server, or re-implement the interface for even more control over the resolution process
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
// set of fallback DNS servers (eg, domain registrars) to try as a fallback. each entry should be "ip:port", eg "8.8.8.8:53"
FallbackDNSServers []string
}
var _ Directory = (*BaseDirectory)(nil)
func (d *BaseDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error) {
h = h.Normalize()
did, err := d.ResolveHandle(ctx, h)
if err != nil {
return nil, err
}
doc, err := d.ResolveDID(ctx, did)
if err != nil {
return nil, err
}
ident := ParseIdentity(doc)
declared, err := ident.DeclaredHandle()
if err != nil {
return nil, err
}
if declared != h {
return nil, ErrHandleMismatch
}
ident.Handle = declared
return &ident, nil
}
func (d *BaseDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error) {
doc, err := d.ResolveDID(ctx, did)
if err != nil {
return nil, err
}
ident := ParseIdentity(doc)
declared, err := ident.DeclaredHandle()
if errors.Is(err, ErrHandleNotDeclared) {
ident.Handle = syntax.HandleInvalid
} else if err != nil {
return nil, err
} else {
// if a handle was declared, resolve it
resolvedDID, err := d.ResolveHandle(ctx, declared)
if err != nil {
if errors.Is(err, ErrHandleNotFound) || errors.Is(err, ErrHandleResolutionFailed) {
ident.Handle = syntax.HandleInvalid
} else {
return nil, err
}
} else if resolvedDID != did {
ident.Handle = syntax.HandleInvalid
} else {
ident.Handle = declared
}
}
return &ident, nil
}
func (d *BaseDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error) {
handle, err := a.AsHandle()
if nil == err { // if *not* an error
return d.LookupHandle(ctx, handle)
}
did, err := a.AsDID()
if nil == err { // if *not* an error
return d.LookupDID(ctx, did)
}
return nil, fmt.Errorf("at-identifier neither a Handle nor a DID")
}
func (d *BaseDirectory) Purge(ctx context.Context, a syntax.AtIdentifier) error {
return nil
}