func (ctx *Context) GetImageLayerHandler(w http.ResponseWriter, r *http.Request) { imageId := mux.Vars(r)["imageId"] imageReader, err := ctx.storage.StreamRead(storage.ImageLayerPath(imageId)) if err != nil { sendResponse(w, "image not found", 404, nil, false) return } defer imageReader.Close() io.Copy(w, imageReader) }
func (ctx *Context) computeImageChecksum(algo string, imageId string, jsonData []byte) (string, error) { if algo != "sha256" { return "", fmt.Errorf("bad algorithm %s, only sha256 supported right now", algo) } hash := sha256.New() fmt.Fprintf(hash, "%s\n", jsonData) reader, err := ctx.storage.StreamRead(storage.ImageLayerPath(imageId)) if err != nil { return "", fmt.Errorf("couldn't read image for checksumming", algo) } io.Copy(hash, reader) return fmt.Sprintf("%x", hash.Sum(nil)), nil }
func (ctx *Context) PutImageLayerHandler(w http.ResponseWriter, r *http.Request) { imageId := mux.Vars(r)["imageId"] jsonData, err := ctx.storage.GetContent(storage.ImageJsonPath(imageId)) if err != nil { sendResponse(w, "Image's JSON not found", 404, nil, false) return } checksum, err := ctx.storage.GetContent(storage.ImageChecksumPath(imageId)) if err != nil { sendResponse(w, "Image's checksum not found", 404, nil, false) return } layerPath := storage.ImageLayerPath(imageId) markPath := storage.ImageMarkPath(imageId) if layerExists, err := ctx.storage.Exists(layerPath); layerExists == true && err == nil { if markExists, err := ctx.storage.Exists(markPath); markExists == false || err != nil { sendResponse(w, "Image already exists", 409, nil, false) return } } writer, err := ctx.storage.StreamWrite(layerPath) if err != nil { sendResponse(w, "Couldn't write to layer file", 500, nil, false) return } io.Copy(writer, r.Body) checksumParts := strings.Split(string(checksum), ":") computedChecksum, err := ctx.computeImageChecksum(checksumParts[0], imageId, jsonData) if err != nil || computedChecksum != strings.ToLower(checksumParts[1]) { sendResponse(w, "Checksum mismatch, ignoring the layer", 400, nil, false) return } ctx.storage.Remove(markPath) sendResponse(w, nil, http.StatusOK, nil, false) }