// processGet handles an image GET request. func (h *imagesDownloadHandler) processGet(r *http.Request, resp http.ResponseWriter, st *state.State) error { // Get the parameters from the query. kind := r.URL.Query().Get(":kind") series := r.URL.Query().Get(":series") arch := r.URL.Query().Get(":arch") modelUUID := r.URL.Query().Get(":modeluuid") // Get the image details from storage. metadata, imageReader, err := h.loadImage(st, modelUUID, kind, series, arch) if err != nil { return errors.Annotate(err, "error getting image from storage") } defer imageReader.Close() // Stream the image to the caller. logger.Debugf("streaming image from state blobstore: %+v", metadata) resp.Header().Set("Content-Type", "application/x-tar-gz") resp.Header().Set("Digest", params.EncodeChecksum(metadata.SHA256)) resp.Header().Set("Content-Length", fmt.Sprint(metadata.Size)) resp.WriteHeader(http.StatusOK) if _, err := io.Copy(resp, imageReader); err != nil { return errors.Annotate(err, "while streaming image") } return nil }
func (h *backupHandler) sendFile(file io.Reader, checksum string, resp http.ResponseWriter) error { // We don't set the Content-Length header, leaving it at -1. resp.Header().Set("Content-Type", params.ContentTypeRaw) resp.Header().Set("Digest", params.EncodeChecksum(checksum)) resp.WriteHeader(http.StatusOK) if _, err := io.Copy(resp, file); err != nil { return errors.Annotate(err, "while streaming archive") } return nil }