A vibe coded tangled fork which supports pijul.
at master 88 lines 2.5 kB view raw
1package xrpc 2 3import ( 4 "context" 5 "fmt" 6 "io" 7 "net/http" 8 "slices" 9 10 "github.com/bluesky-social/indigo/atproto/atclient" 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 "github.com/go-git/go-git/v5/plumbing/object" 13 "tangled.org/core/knotserver/git" 14) 15 16func (x *Xrpc) GetBlob(w http.ResponseWriter, r *http.Request) { 17 var ( 18 repoQuery = r.URL.Query().Get("repo") 19 ref = r.URL.Query().Get("ref") // ref can be empty (git.Open handles this) 20 path = r.URL.Query().Get("path") 21 ) 22 23 repo, err := syntax.ParseATURI(repoQuery) 24 if err != nil || repo.RecordKey() == "" { 25 writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: fmt.Sprintf("repo parameter invalid: %s", repoQuery)}) 26 return 27 } 28 29 l := x.logger.With("repo", repo, "ref", ref, "path", path) 30 31 if path == "" { 32 writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: "missing path parameter"}) 33 return 34 } 35 36 file, err := x.getFile(r.Context(), repo, ref, path) 37 if err != nil { 38 l.Warn("local mirror failed, trying proxy", "err", err) 39 if x.proxyToKnot(w, r, repo) { 40 return 41 } 42 writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "failed to get blob"}) 43 return 44 } 45 46 reader, err := file.Reader() 47 if err != nil { 48 l.Error("failed to read blob", "err", err) 49 writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "failed to read the blob"}) 50 return 51 } 52 defer reader.Close() 53 54 w.Header().Set("Content-Type", "application/octet-stream") 55 if _, err := io.Copy(w, reader); err != nil { 56 l.Error("failed to serve the blob", "err", err) 57 } 58} 59 60func (x *Xrpc) getFile(ctx context.Context, repo syntax.ATURI, ref, path string) (*object.File, error) { 61 repoPath, err := x.makeRepoPath(ctx, repo) 62 if err != nil { 63 return nil, fmt.Errorf("resolving repo at-uri: %w", err) 64 } 65 66 gr, err := git.Open(repoPath, ref) 67 if err != nil { 68 return nil, fmt.Errorf("opening git repo: %w", err) 69 } 70 71 return gr.File(path) 72} 73 74var textualMimeTypes = []string{ 75 "application/json", 76 "application/xml", 77 "application/yaml", 78 "application/x-yaml", 79 "application/toml", 80 "application/javascript", 81 "application/ecmascript", 82} 83 84// isTextualMimeType returns true if the MIME type represents textual content 85// that should be served as text/plain for security reasons 86func isTextualMimeType(mimeType string) bool { 87 return slices.Contains(textualMimeTypes, mimeType) 88}