func (ctx *Context) GetImageJsonHandler(w http.ResponseWriter, r *http.Request) { imageId := mux.Vars(r)["imageId"] data, err := ctx.storage.GetContent(storage.ImageJsonPath(imageId)) if err != nil { sendResponse(w, "Image not found", 404, nil, false) return } headers := make(map[string]string) if checksum, err := ctx.storage.GetContent(storage.ImageChecksumPath(imageId)); err != nil { headers["X-Docker-Checksum"] = string(checksum) } sendResponse(w, data, 200, headers, true) }
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) }
func (ctx *Context) PutImageJsonHandler(w http.ResponseWriter, r *http.Request) { imageId := mux.Vars(r)["imageId"] body, err := ioutil.ReadAll(r.Body) if err != nil { sendResponse(w, "Couldn't read request body", 500, nil, false) return } var data map[string]string if err := json.Unmarshal(body, &data); err != nil { sendResponse(w, "Invalid JSON", 400, nil, false) return } if _, ok := data["id"]; !ok { sendResponse(w, "Missing Key `id' in JSON", 400, nil, false) return } checksum := r.Header.Get("X-Docker-Checksum") if checksum == "" { sendResponse(w, "Missing Image's checksum", 400, nil, false) return } checksumParts := strings.Split(string(checksum), ":") if len(checksumParts) != 2 { sendResponse(w, "Invalid checksum format", 400, nil, false) return } if checksumParts[0] != "sha256" { sendResponse(w, "Checksum algorithm not supported", 400, nil, false) return } checksumPath := storage.ImageChecksumPath(imageId) ctx.storage.PutContent(checksumPath, []byte(checksum)) if imageId != data["id"] { sendResponse(w, "JSON data contains invalid id", 400, nil, false) return } parentId, ok := data["parent"] exists, err := ctx.storage.Exists(storage.ImageJsonPath(parentId)) if ok && !exists && err == nil { sendResponse(w, "Image depends on a non existing parent", 400, nil, false) return } jsonPath := storage.ImageJsonPath(imageId) markPath := storage.ImageMarkPath(imageId) jsonExists, err := ctx.storage.Exists(jsonPath) if err != nil { sendResponse(w, "Couldn't check if JSON exists", 500, nil, false) return } markExists, err := ctx.storage.Exists(markPath) if err != nil { sendResponse(w, "Couldn't check if mark exists", 500, nil, false) return } if jsonExists && !markExists { sendResponse(w, "Image already exists", 409, nil, false) return } ctx.storage.PutContent(markPath, []byte("true")) ctx.storage.PutContent(jsonPath, body) if err := ctx.generateAncestry(imageId, parentId); err != nil { sendResponse(w, fmt.Sprintf("Couldn't generate ancestry: %s", err), 500, nil, false) return } sendResponse(w, nil, 200, nil, false) }