forked from hailey.at/cocoon
An atproto PDS written in Go

better http client usage

+26 -61
identity/identity.go
··· 10 10 "strings" 11 11 12 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 + "github.com/bluesky-social/indigo/util" 13 14 ) 14 15 15 - func ResolveHandle(ctx context.Context, handle string) (string, error) { 16 + func ResolveHandle(ctx context.Context, cli *http.Client, handle string) (string, error) { 17 + if cli == nil { 18 + cli = util.RobustHTTPClient() 19 + } 20 + 16 21 var did string 17 22 18 23 _, err := syntax.ParseHandle(handle) ··· 71 76 return did, nil 72 77 } 73 78 74 - type DidDoc struct { 75 - Context []string `json:"@context"` 76 - Id string `json:"id"` 77 - AlsoKnownAs []string `json:"alsoKnownAs"` 78 - VerificationMethods []DidDocVerificationMethod `json:"verificationMethods"` 79 - Service []DidDocService `json:"service"` 80 - } 81 - 82 - type DidDocVerificationMethod struct { 83 - Id string `json:"id"` 84 - Type string `json:"type"` 85 - Controller string `json:"controller"` 86 - PublicKeyMultibase string `json:"publicKeyMultibase"` 87 - } 88 - 89 - type DidDocService struct { 90 - Id string `json:"id"` 91 - Type string `json:"type"` 92 - ServiceEndpoint string `json:"serviceEndpoint"` 93 - } 94 - 95 - type DidData struct { 96 - Did string `json:"did"` 97 - VerificationMethods map[string]string `json:"verificationMethods"` 98 - RotationKeys []string `json:"rotationKeys"` 99 - AlsoKnownAs []string `json:"alsoKnownAs"` 100 - Services map[string]OperationService `json:"services"` 101 - } 102 - 103 - type OperationService struct { 104 - Type string `json:"type"` 105 - Endpoint string `json:"endpoint"` 106 - } 79 + func FetchDidDoc(ctx context.Context, cli *http.Client, did string) (*DidDoc, error) { 80 + if cli == nil { 81 + cli = util.RobustHTTPClient() 82 + } 107 83 108 - type DidLog []DidLogEntry 109 - 110 - type DidLogEntry struct { 111 - Sig string `json:"sig"` 112 - Prev *string `json:"prev"` 113 - Type string `json:"string"` 114 - Services map[string]OperationService `json:"services"` 115 - AlsoKnownAs []string `json:"alsoKnownAs"` 116 - RotationKeys []string `json:"rotationKeys"` 117 - VerificationMethods map[string]string `json:"verificationMethods"` 118 - } 119 - 120 - type DidAuditEntry struct { 121 - Did string `json:"did"` 122 - Operation DidLogEntry `json:"operation"` 123 - Cid string `json:"cid"` 124 - Nullified bool `json:"nullified"` 125 - CreatedAt string `json:"createdAt"` 126 - } 127 - 128 - type DidAuditLog []DidAuditEntry 129 - 130 - func FetchDidDoc(ctx context.Context, did string) (*DidDoc, error) { 131 84 var ustr string 132 85 if strings.HasPrefix(did, "did:plc:") { 133 86 ustr = fmt.Sprintf("https://plc.directory/%s", did) ··· 161 114 return &diddoc, nil 162 115 } 163 116 164 - func FetchDidData(ctx context.Context, did string) (*DidData, error) { 117 + func FetchDidData(ctx context.Context, cli *http.Client, did string) (*DidData, error) { 118 + if cli == nil { 119 + cli = util.RobustHTTPClient() 120 + } 121 + 165 122 var ustr string 166 123 ustr = fmt.Sprintf("https://plc.directory/%s/data", did) 167 124 ··· 189 146 return &diddata, nil 190 147 } 191 148 192 - func FetchDidAuditLog(ctx context.Context, did string) (DidAuditLog, error) { 149 + func FetchDidAuditLog(ctx context.Context, cli *http.Client, did string) (DidAuditLog, error) { 150 + if cli == nil { 151 + cli = util.RobustHTTPClient() 152 + } 153 + 193 154 var ustr string 194 155 ustr = fmt.Sprintf("https://plc.directory/%s/log/audit", did) 195 156 ··· 217 178 return didlog, nil 218 179 } 219 180 220 - func ResolveService(ctx context.Context, did string) (string, error) { 221 - diddoc, err := FetchDidDoc(ctx, did) 181 + func ResolveService(ctx context.Context, cli *http.Client, did string) (string, error) { 182 + if cli == nil { 183 + cli = util.RobustHTTPClient() 184 + } 185 + 186 + diddoc, err := FetchDidDoc(ctx, cli, did) 222 187 if err != nil { 223 188 return "", err 224 189 }
+10 -3
identity/passport.go
··· 2 2 3 3 import ( 4 4 "context" 5 + "net/http" 5 6 "sync" 6 7 ) 7 8 ··· 16 17 } 17 18 18 19 type Passport struct { 20 + h *http.Client 19 21 bc BackingCache 20 22 lk sync.Mutex 21 23 } 22 24 23 - func NewPassport(bc BackingCache) *Passport { 25 + func NewPassport(h *http.Client, bc BackingCache) *Passport { 26 + if h == nil { 27 + h = http.DefaultClient 28 + } 29 + 24 30 return &Passport{ 31 + h: h, 25 32 bc: bc, 26 33 lk: sync.Mutex{}, 27 34 } ··· 40 47 p.lk.Lock() // this is pretty pathetic, and i should rethink this. but for now, fuck it 41 48 defer p.lk.Unlock() 42 49 43 - doc, err := FetchDidDoc(ctx, did) 50 + doc, err := FetchDidDoc(ctx, p.h, did) 44 51 if err != nil { 45 52 return nil, err 46 53 } ··· 60 67 } 61 68 } 62 69 63 - did, err := ResolveHandle(ctx, handle) 70 + did, err := ResolveHandle(ctx, p.h, handle) 64 71 if err != nil { 65 72 return "", err 66 73 }
+57
identity/types.go
··· 1 + package identity 2 + 3 + type DidDoc struct { 4 + Context []string `json:"@context"` 5 + Id string `json:"id"` 6 + AlsoKnownAs []string `json:"alsoKnownAs"` 7 + VerificationMethods []DidDocVerificationMethod `json:"verificationMethods"` 8 + Service []DidDocService `json:"service"` 9 + } 10 + 11 + type DidDocVerificationMethod struct { 12 + Id string `json:"id"` 13 + Type string `json:"type"` 14 + Controller string `json:"controller"` 15 + PublicKeyMultibase string `json:"publicKeyMultibase"` 16 + } 17 + 18 + type DidDocService struct { 19 + Id string `json:"id"` 20 + Type string `json:"type"` 21 + ServiceEndpoint string `json:"serviceEndpoint"` 22 + } 23 + 24 + type DidData struct { 25 + Did string `json:"did"` 26 + VerificationMethods map[string]string `json:"verificationMethods"` 27 + RotationKeys []string `json:"rotationKeys"` 28 + AlsoKnownAs []string `json:"alsoKnownAs"` 29 + Services map[string]OperationService `json:"services"` 30 + } 31 + 32 + type OperationService struct { 33 + Type string `json:"type"` 34 + Endpoint string `json:"endpoint"` 35 + } 36 + 37 + type DidLog []DidLogEntry 38 + 39 + type DidLogEntry struct { 40 + Sig string `json:"sig"` 41 + Prev *string `json:"prev"` 42 + Type string `json:"string"` 43 + Services map[string]OperationService `json:"services"` 44 + AlsoKnownAs []string `json:"alsoKnownAs"` 45 + RotationKeys []string `json:"rotationKeys"` 46 + VerificationMethods map[string]string `json:"verificationMethods"` 47 + } 48 + 49 + type DidAuditEntry struct { 50 + Did string `json:"did"` 51 + Operation DidLogEntry `json:"operation"` 52 + Cid string `json:"cid"` 53 + Nullified bool `json:"nullified"` 54 + CreatedAt string `json:"createdAt"` 55 + } 56 + 57 + type DidAuditLog []DidAuditEntry
+8 -2
plc/client.go
··· 15 15 16 16 "github.com/bluesky-social/indigo/atproto/crypto" 17 17 "github.com/bluesky-social/indigo/util" 18 + "github.com/haileyok/cocoon/identity" 18 19 ) 19 20 20 21 type Client struct { ··· 25 26 } 26 27 27 28 type ClientArgs struct { 29 + H *http.Client 28 30 Service string 29 31 RotationKey []byte 30 32 PdsHostname string ··· 35 37 args.Service = "https://plc.directory" 36 38 } 37 39 40 + if args.H == nil { 41 + args.H = util.RobustHTTPClient() 42 + } 43 + 38 44 rk, err := crypto.ParsePrivateBytesK256([]byte(args.RotationKey)) 39 45 if err != nil { 40 46 return nil, err 41 47 } 42 48 43 49 return &Client{ 44 - h: util.RobustHTTPClient(), 50 + h: args.H, 45 51 service: args.Service, 46 52 rotationKey: rk, 47 53 pdsHostname: args.PdsHostname, ··· 80 86 AlsoKnownAs: []string{ 81 87 "at://" + handle, 82 88 }, 83 - Services: map[string]OperationService{ 89 + Services: map[string]identity.OperationService{ 84 90 "atproto_pds": { 85 91 Type: "AtprotoPersonalDataServer", 86 92 Endpoint: "https://" + c.pdsHostname,
+1 -1
server/handle_identity_update_handle.go
··· 39 39 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 40 40 41 41 if strings.HasPrefix(repo.Repo.Did, "did:plc:") { 42 - log, err := identity.FetchDidAuditLog(ctx, repo.Repo.Did) 42 + log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 43 43 if err != nil { 44 44 s.logger.Error("error fetching doc", "error", err) 45 45 return helpers.ServerError(e, nil)
+1 -1
server/handle_server_create_account.go
··· 116 116 return helpers.ServerError(e, nil) 117 117 } 118 118 119 - did, op, err := s.plcClient.CreateDID(e.Request().Context(), k, "", request.Handle) 119 + did, op, err := s.plcClient.CreateDID(k, "", request.Handle) 120 120 if err != nil { 121 121 s.logger.Error("error creating operation", "endpoint", "com.atproto.server.createAccount", "error", err) 122 122 return helpers.ServerError(e, nil)
+7 -1
server/server.go
··· 15 15 "github.com/bluesky-social/indigo/api/atproto" 16 16 "github.com/bluesky-social/indigo/atproto/syntax" 17 17 "github.com/bluesky-social/indigo/events" 18 + "github.com/bluesky-social/indigo/util" 18 19 "github.com/bluesky-social/indigo/xrpc" 19 20 "github.com/go-playground/validator" 20 21 "github.com/golang-jwt/jwt/v4" ··· 31 32 ) 32 33 33 34 type Server struct { 35 + http *http.Client 34 36 httpd *http.Server 35 37 echo *echo.Echo 36 38 db *gorm.DB ··· 268 270 return nil, err 269 271 } 270 272 273 + h := util.RobustHTTPClient() 274 + 271 275 plcClient, err := plc.NewClient(&plc.ClientArgs{ 276 + H: h, 272 277 Service: "https://plc.directory", 273 278 PdsHostname: args.Hostname, 274 279 RotationKey: rkbytes, ··· 293 298 } 294 299 295 300 s := &Server{ 301 + http: h, 296 302 httpd: httpd, 297 303 echo: e, 298 304 logger: args.Logger, ··· 308 314 Relays: args.Relays, 309 315 }, 310 316 evtman: events.NewEventManager(events.NewMemPersister()), 311 - passport: identity.NewPassport(identity.NewMemCache(10_000)), 317 + passport: identity.NewPassport(h, identity.NewMemCache(10_000)), 312 318 } 313 319 314 320 s.repoman = NewRepoMan(s) // TODO: this is way too lazy, stop it