A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
0
fork

Configure Feed

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

try implement sync.GetRecord

+76 -1
+1 -1
go.mod
··· 12 12 github.com/gorilla/mux v1.8.1 13 13 github.com/gorilla/websocket v1.5.3 14 14 github.com/ipfs/go-cid v0.4.1 15 + github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4 15 16 github.com/klauspost/compress v1.18.0 16 17 github.com/mattn/go-sqlite3 v1.14.32 17 18 github.com/opencontainers/go-digest v1.0.0 ··· 68 69 github.com/ipfs/go-merkledag v0.11.0 // indirect 69 70 github.com/ipfs/go-metrics-interface v0.0.1 // indirect 70 71 github.com/ipfs/go-verifcid v0.0.3 // indirect 71 - github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4 // indirect 72 72 github.com/ipld/go-codec-dagpb v1.6.0 // indirect 73 73 github.com/ipld/go-ipld-prime v0.21.0 // indirect 74 74 github.com/jackc/pgpassfile v1.0.0 // indirect
+75
pkg/hold/pds/xrpc.go
··· 1 1 package pds 2 2 3 3 import ( 4 + "bytes" 4 5 "encoding/json" 5 6 "fmt" 6 7 "net/http" 7 8 "strings" 9 + 10 + "github.com/ipfs/go-cid" 11 + "github.com/ipld/go-car" 12 + carutil "github.com/ipld/go-car/util" 8 13 ) 9 14 10 15 // XRPC handler for ATProto endpoints ··· 63 68 64 69 // Sync endpoints 65 70 mux.HandleFunc("/xrpc/com.atproto.sync.listRepos", corsMiddleware(h.HandleListRepos)) 71 + mux.HandleFunc("/xrpc/com.atproto.sync.getRecord", corsMiddleware(h.HandleSyncGetRecord)) 66 72 67 73 // Blob endpoints (wrap existing presigned URL logic) 68 74 mux.HandleFunc("/xrpc/com.atproto.repo.uploadBlob", corsMiddleware(h.HandleUploadBlob)) ··· 238 244 239 245 w.Header().Set("Content-Type", "application/json") 240 246 json.NewEncoder(w).Encode(response) 247 + } 248 + 249 + // HandleSyncGetRecord returns a single record as a CAR file for sync 250 + func (h *XRPCHandler) HandleSyncGetRecord(w http.ResponseWriter, r *http.Request) { 251 + if r.Method != http.MethodGet { 252 + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) 253 + return 254 + } 255 + 256 + did := r.URL.Query().Get("did") 257 + collection := r.URL.Query().Get("collection") 258 + rkey := r.URL.Query().Get("rkey") 259 + 260 + if did == "" || collection == "" || rkey == "" { 261 + http.Error(w, "missing required parameters", http.StatusBadRequest) 262 + return 263 + } 264 + 265 + if did != h.pds.DID() { 266 + http.Error(w, "invalid did", http.StatusBadRequest) 267 + return 268 + } 269 + 270 + // Only support crew collection for now 271 + if collection != CrewCollection { 272 + http.Error(w, "collection not found", http.StatusNotFound) 273 + return 274 + } 275 + 276 + // Get the record CID and raw bytes 277 + recordCID, _, err := h.pds.GetCrewMember(r.Context(), rkey) 278 + if err != nil { 279 + http.Error(w, fmt.Sprintf("failed to get record: %v", err), http.StatusNotFound) 280 + return 281 + } 282 + 283 + // Get the raw block from the blockstore 284 + blk, err := h.pds.repo.Blockstore().Get(r.Context(), recordCID) 285 + if err != nil { 286 + http.Error(w, fmt.Sprintf("failed to get record block: %v", err), http.StatusInternalServerError) 287 + return 288 + } 289 + 290 + // Write CAR file with the single record 291 + w.Header().Set("Content-Type", "application/vnd.ipld.car") 292 + 293 + // Create a buffer to write the CAR data 294 + var buf bytes.Buffer 295 + 296 + // Create CAR header with the record CID as root 297 + header := &car.CarHeader{ 298 + Roots: []cid.Cid{recordCID}, 299 + Version: 1, 300 + } 301 + 302 + // Write the CAR header 303 + if err := car.WriteHeader(header, &buf); err != nil { 304 + http.Error(w, fmt.Sprintf("failed to write CAR header: %v", err), http.StatusInternalServerError) 305 + return 306 + } 307 + 308 + // Write the block using LdWrite 309 + if err := carutil.LdWrite(&buf, recordCID.Bytes(), blk.RawData()); err != nil { 310 + http.Error(w, fmt.Sprintf("failed to write block to CAR: %v", err), http.StatusInternalServerError) 311 + return 312 + } 313 + 314 + // Write the CAR data to the response 315 + w.Write(buf.Bytes()) 241 316 } 242 317 243 318 // HandleUploadBlob wraps existing presigned upload URL logic