Monorepo for Tangled tangled.org
5

Configure Feed

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

1package xrpc 2 3import ( 4 "database/sql" 5 "encoding/json" 6 "errors" 7 "log/slog" 8 "net/http" 9 "time" 10 11 "github.com/bluesky-social/indigo/atproto/atclient" 12 "github.com/bluesky-social/indigo/util/ssrf" 13 "github.com/go-chi/chi/v5" 14 "github.com/redis/go-redis/v9" 15 "tangled.org/core/api/tangled" 16 "tangled.org/core/idresolver" 17 "tangled.org/core/knotmirror/config" 18 "tangled.org/core/knotmirror/knotstream" 19 "tangled.org/core/knotmirror/repoindexer" 20 "tangled.org/core/log" 21) 22 23type Xrpc struct { 24 cfg *config.Config 25 db *sql.DB 26 rdb *redis.Client 27 indexer *repoindexer.Indexer 28 resolver *idresolver.Resolver 29 ks *knotstream.KnotStream 30 logger *slog.Logger 31 httpClient *http.Client 32 inflight *inflightTracker 33} 34 35func New(logger *slog.Logger, cfg *config.Config, db *sql.DB, rdb *redis.Client, indexer *repoindexer.Indexer, resolver *idresolver.Resolver, ks *knotstream.KnotStream) *Xrpc { 36 httpClient := &http.Client{ 37 Timeout: 30 * time.Second, 38 } 39 if cfg.KnotSSRF { 40 httpClient.Transport = ssrf.PublicOnlyTransport() 41 } 42 return &Xrpc{ 43 cfg: cfg, 44 db: db, 45 rdb: rdb, 46 indexer: indexer, 47 resolver: resolver, 48 ks: ks, 49 logger: log.SubLogger(logger, "xrpc"), 50 httpClient: httpClient, 51 inflight: newInflightTracker(), 52 } 53} 54 55func (x *Xrpc) Router() http.Handler { 56 r := chi.NewRouter() 57 r.Use(metricsMiddleware) 58 59 r.Group(func(r chi.Router) { 60 r.Use(x.inflight.middleware) 61 62 r.Get("/"+tangled.GitTempGetArchiveNSID, x.GetArchive) 63 r.Get("/"+tangled.GitTempGetBlobNSID, x.GetBlob) 64 r.Get("/"+tangled.GitTempGetBranchNSID, x.GetBranch) 65 // r.Get("/"+tangled.GitTempGetCommitNSID, x.GetCommit) // todo 66 // r.Get("/"+tangled.GitTempGetDiffNSID, x.GetDiff) // todo 67 r.Get("/"+tangled.GitTempGetEntryNSID, x.GetEntry) // todo 68 // r.Get("/"+tangled.GitTempGetHeadNSID, x.GetHead) // todo 69 r.Get("/"+tangled.GitTempGetTagNSID, x.GetTag) // using types.Response 70 r.Get("/"+tangled.GitTempGetTreeNSID, x.GetTree) 71 r.Get("/"+tangled.GitTempListBranchesNSID, x.ListBranches) // wip, unknown output 72 r.Get("/"+tangled.GitTempListCommitsNSID, x.ListCommits) 73 r.Get("/"+tangled.GitTempListLanguagesNSID, x.ListLanguages) 74 r.Get("/"+tangled.GitTempListTagsNSID, x.ListTags) 75 r.Post("/"+tangled.SyncRequestCrawlNSID, x.RequestCrawl) 76 }) 77 78 return r 79} 80 81func writeJson(w http.ResponseWriter, status int, response any) error { 82 w.Header().Set("Content-Type", "application/json") 83 w.WriteHeader(status) 84 if err := json.NewEncoder(w).Encode(response); err != nil { 85 return err 86 } 87 return nil 88} 89 90func writeErr(w http.ResponseWriter, err error) error { 91 var apiErr *atclient.APIError 92 if errors.As(err, &apiErr) { 93 return writeJson(w, apiErr.StatusCode, atclient.ErrorBody{Name: apiErr.Name, Message: apiErr.Message}) 94 } 95 return writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "internal server error"}) 96}