A fork of the Cocoon PDS but being made more distributed.
11

Configure Feed

Select the types of activity you want to include in your feed.

better http client usage

Hailey (Mar 29, 2025, 4:40 PM -0700) d56b9154 b8a45307

+110 -69
+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