···
···
136
-
// TODO: proper statuses here on early exit
func (rp *Repo) DownloadArtifact(w http.ResponseWriter, r *http.Request) {
138
-
tagParam := chi.URLParam(r, "tag")
139
-
filename := chi.URLParam(r, "file")
f, err := rp.repoResolver.Resolve(r)
log.Println("failed to get repo and knot", err)
141
+
http.Error(w, "failed to resolve repo", http.StatusInternalServerError)
145
+
tagParam := chi.URLParam(r, "tag")
146
+
filename := chi.URLParam(r, "file")
tag, err := rp.resolveTag(r.Context(), f, tagParam)
log.Println("failed to resolve tag", err)
···
153
-
client, err := rp.oauth.AuthorizedClient(r)
155
-
log.Println("failed to get authorized client", err)
artifacts, err := db.GetArtifact(
db.FilterEq("repo_at", f.RepoAt()),
···
log.Println("failed to get artifacts", err)
163
+
http.Error(w, "failed to get artifact", http.StatusInternalServerError)
170
-
log.Printf("too many or too little artifacts found")
168
+
log.Printf("too many or too few artifacts found")
169
+
http.Error(w, "artifact not found", http.StatusNotFound)
176
-
getBlobResp, err := client.SyncGetBlob(r.Context(), artifact.BlobCid.String(), artifact.Did)
175
+
ownerPds := f.OwnerId.PDSEndpoint()
176
+
url, _ := url.Parse(fmt.Sprintf("%s/xrpc/com.atproto.sync.getBlob", ownerPds))
178
+
q.Set("cid", artifact.BlobCid.String())
179
+
q.Set("did", artifact.Did)
180
+
url.RawQuery = q.Encode()
182
+
req, err := http.NewRequest(http.MethodGet, url.String(), nil)
178
-
log.Println("failed to get blob from pds", err)
184
+
log.Println("failed to create request", err)
185
+
http.Error(w, "failed to create request", http.StatusInternalServerError)
188
+
req.Header.Set("Content-Type", "application/json")
182
-
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filename))
183
-
w.Write(getBlobResp)
190
+
resp, err := http.DefaultClient.Do(req)
192
+
log.Println("failed to make request", err)
193
+
http.Error(w, "failed to make request to PDS", http.StatusInternalServerError)
196
+
defer resp.Body.Close()
198
+
// copy status code and relevant headers from upstream response
199
+
w.WriteHeader(resp.StatusCode)
200
+
for key, values := range resp.Header {
201
+
for _, v := range values {
202
+
w.Header().Add(key, v)
206
+
// stream the body directly to the client
207
+
if _, err := io.Copy(w, resp.Body); err != nil {
208
+
log.Println("error streaming response to client:", err)
// TODO: proper statuses here on early exit