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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package pdsclient
import (
"crypto/tls"
"fmt"
"net/http"
"strings"
"time"
"github.com/bluesky-social/indigo/atproto/syntax"
pdsv1alpha1 "github.com/johnandersen777/socialweb-computer-kcp/api/pds/v1alpha1"
)
type CRRef struct {
RemotePDS *pdsv1alpha1.RemotePDS
}
type Ref interface {
isPDSRef()
}
func (LocalRef) isPDSRef() {}
func (CRRef) isPDSRef() {}
type Resolver struct {
Handlers Handlers
HTTPClient *http.Client
TLS *tls.Config
Tokens TokenSource
DPoP DPoPSource
Timeout time.Duration
}
func (r *Resolver) Resolve(ref Ref) (PDS, error) {
if r == nil {
return nil, fmt.Errorf("%w: resolver is nil", ErrInvalidConfig)
}
if ref == nil {
return nil, fmt.Errorf("%w: nil reference", ErrInvalidRef)
}
switch value := ref.(type) {
case LocalRef:
return r.ResolveLocal(value)
case CRRef:
return r.ResolveCR(value)
default:
return nil, fmt.Errorf("%w: unknown reference", ErrInvalidRef)
}
}
func (r *Resolver) ResolveLocal(ref LocalRef) (PDS, error) {
if r == nil {
return nil, fmt.Errorf("%w: resolver is nil", ErrInvalidConfig)
}
if r.Handlers == nil {
return nil, fmt.Errorf("%w: local handler registry is required", ErrInvalidConfig)
}
baseURL, err := ref.baseURL()
if err != nil {
return nil, err
}
return NewLocal(LocalConfig{
Handlers: r.Handlers,
BaseURL: baseURL,
Tokens: r.Tokens,
DPoP: r.DPoP,
Timeout: r.Timeout,
})
}
func (r *Resolver) ResolveCR(ref CRRef) (PDS, error) {
if r == nil {
return nil, fmt.Errorf("%w: resolver is nil", ErrInvalidConfig)
}
if ref.RemotePDS == nil {
return nil, fmt.Errorf("%w: RemotePDS is nil", ErrInvalidRef)
}
spec := ref.RemotePDS.Spec
name := ref.RemotePDS.Name
if spec.Suspend {
return nil, fmt.Errorf("%w: RemotePDS %s is suspended", ErrUnavailable, name)
}
if strings.TrimSpace(spec.URL) == "" {
return nil, fmt.Errorf("%w: RemotePDS %s has no URL", ErrInvalidConfig, name)
}
did, err := syntax.ParseDID(strings.TrimSpace(spec.DID))
if err != nil {
return nil, fmt.Errorf("%w: RemotePDS %s has an invalid did", ErrInvalidConfig, name)
}
tlsConfig, err := r.remoteTLS(spec, name)
if err != nil {
return nil, err
}
return NewRemote(RemoteConfig{
BaseURL: spec.URL,
DID: did,
HTTPClient: r.HTTPClient,
TLS: tlsConfig,
Tokens: r.Tokens,
DPoP: r.DPoP,
Timeout: r.Timeout,
})
}
func (r *Resolver) remoteTLS(spec pdsv1alpha1.RemotePDSSpec, name string) (*tls.Config, error) {
var config *tls.Config
if r.TLS != nil {
config = r.TLS.Clone()
} else if r.HTTPClient != nil {
if transport, ok := r.HTTPClient.Transport.(*http.Transport); ok && transport.TLSClientConfig != nil {
config = transport.TLSClientConfig.Clone()
}
}
if !spec.TLS.Enabled {
return config, nil
}
if config == nil && (spec.TLS.CARef != nil || spec.TLS.CASecretRef != nil) && r.HTTPClient == nil {
return nil, fmt.Errorf("%w: RemotePDS %s needs a TLS config for its CA bundle", ErrInvalidConfig, name)
}
if config == nil {
config = &tls.Config{}
}
if serverName := strings.TrimSpace(spec.TLS.ServerName); serverName != "" {
config.ServerName = serverName
}
return config, nil
}