mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-29 04:06:58 +00:00
try implement sync.GetRecord
This commit is contained in:
@@ -12,6 +12,7 @@ require (
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/ipfs/go-cid v0.4.1
|
||||
github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/mattn/go-sqlite3 v1.14.32
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
@@ -68,7 +69,6 @@ require (
|
||||
github.com/ipfs/go-merkledag v0.11.0 // indirect
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
|
||||
github.com/ipfs/go-verifcid v0.0.3 // indirect
|
||||
github.com/ipld/go-car v0.6.1-0.20230509095817-92d28eb23ba4 // indirect
|
||||
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
|
||||
github.com/ipld/go-ipld-prime v0.21.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package pds
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipld/go-car"
|
||||
carutil "github.com/ipld/go-car/util"
|
||||
)
|
||||
|
||||
// XRPC handler for ATProto endpoints
|
||||
@@ -63,6 +68,7 @@ func (h *XRPCHandler) RegisterHandlers(mux *http.ServeMux) {
|
||||
|
||||
// Sync endpoints
|
||||
mux.HandleFunc("/xrpc/com.atproto.sync.listRepos", corsMiddleware(h.HandleListRepos))
|
||||
mux.HandleFunc("/xrpc/com.atproto.sync.getRecord", corsMiddleware(h.HandleSyncGetRecord))
|
||||
|
||||
// Blob endpoints (wrap existing presigned URL logic)
|
||||
mux.HandleFunc("/xrpc/com.atproto.repo.uploadBlob", corsMiddleware(h.HandleUploadBlob))
|
||||
@@ -240,6 +246,75 @@ func (h *XRPCHandler) HandleListRecords(w http.ResponseWriter, r *http.Request)
|
||||
json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
|
||||
// HandleSyncGetRecord returns a single record as a CAR file for sync
|
||||
func (h *XRPCHandler) HandleSyncGetRecord(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
did := r.URL.Query().Get("did")
|
||||
collection := r.URL.Query().Get("collection")
|
||||
rkey := r.URL.Query().Get("rkey")
|
||||
|
||||
if did == "" || collection == "" || rkey == "" {
|
||||
http.Error(w, "missing required parameters", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if did != h.pds.DID() {
|
||||
http.Error(w, "invalid did", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Only support crew collection for now
|
||||
if collection != CrewCollection {
|
||||
http.Error(w, "collection not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the record CID and raw bytes
|
||||
recordCID, _, err := h.pds.GetCrewMember(r.Context(), rkey)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get record: %v", err), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the raw block from the blockstore
|
||||
blk, err := h.pds.repo.Blockstore().Get(r.Context(), recordCID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get record block: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Write CAR file with the single record
|
||||
w.Header().Set("Content-Type", "application/vnd.ipld.car")
|
||||
|
||||
// Create a buffer to write the CAR data
|
||||
var buf bytes.Buffer
|
||||
|
||||
// Create CAR header with the record CID as root
|
||||
header := &car.CarHeader{
|
||||
Roots: []cid.Cid{recordCID},
|
||||
Version: 1,
|
||||
}
|
||||
|
||||
// Write the CAR header
|
||||
if err := car.WriteHeader(header, &buf); err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to write CAR header: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Write the block using LdWrite
|
||||
if err := carutil.LdWrite(&buf, recordCID.Bytes(), blk.RawData()); err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to write block to CAR: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Write the CAR data to the response
|
||||
w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
// HandleUploadBlob wraps existing presigned upload URL logic
|
||||
func (h *XRPCHandler) HandleUploadBlob(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
|
||||
Reference in New Issue
Block a user