in proxy/proxyserver/prefetch.go [149:191]
func (ph *PrefetchHandler) Handle(w http.ResponseWriter, r *http.Request) {
ph.metrics.Counter("requests").Inc(1)
var reqBody prefetchBody
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
writeBadRequestError(w, fmt.Sprintf("failed to decode request body: %s", err), "")
log.With("error", err).Error("Failed to decode request body")
return
}
logger := log.With("trace_id", reqBody.TraceId)
namespace, tag, err := ph.tagParser.ParseTag(reqBody.Tag)
if err != nil {
writeBadRequestError(w, fmt.Sprintf("tag: %s, invalid tag format: %s", reqBody.Tag, err), reqBody.TraceId)
return
}
tagRequest := url.QueryEscape(fmt.Sprintf("%s/%s", namespace, tag))
digest, err := ph.tagClient.Get(tagRequest)
if err != nil {
writeInternalError(w, fmt.Sprintf("tag request: %s, failed to get tag: %s", tagRequest, err), reqBody.TraceId)
return
}
logger.Infof("Namespace: %s, Tag: %s", namespace, tag)
buf := &bytes.Buffer{}
if err := ph.clusterClient.DownloadBlob(namespace, digest, buf); err != nil {
writeInternalError(w, fmt.Sprintf("error downloading manifest blob: %s", err), reqBody.TraceId)
return
}
// Process manifest (ManifestList or single Manifest)
size, digests, err := ph.processManifest(logger, namespace, buf.Bytes())
if err != nil {
writeInternalError(w, fmt.Sprintf("failed to process manifest: %s", err), reqBody.TraceId)
return
}
ph.metrics.SubScope("prefetch").Counter("initiated").Inc(1)
writePrefetchResponse(w, reqBody.Tag, "prefetching initiated successfully", reqBody.TraceId)
// Prefetch blobs asynchronously.
go ph.prefetchBlobs(logger, namespace, digests, size)
}