func receiveUpload(genDst func(int) string, marksuccess func(int) error) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, req *http.Request) { if req.Method != "PUT" { w.WriteHeader(http.StatusNotFound) return } num, err := strconv.Atoi(mux.Vars(req)["num"]) if err != nil { w.WriteHeader(http.StatusNotFound) return } up := getUpload(num) if up == nil { w.WriteHeader(http.StatusNotFound) return } _, err = os.Stat(up.Image) if err == nil { w.WriteHeader(http.StatusConflict) w.Write([]byte("item already uploaded")) return } else if !os.IsNotExist(err) { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(os.Stderr, "%v", err) return } aci, err := os.OpenFile(genDst(num), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(os.Stderr, "%v", err) return } defer aci.Close() _, err = io.Copy(aci, req.Body) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(os.Stderr, "%v", err) return } err = marksuccess(num) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(os.Stderr, "%v", err) return } w.WriteHeader(http.StatusOK) } }
func initiateUpload(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { w.WriteHeader(http.StatusNotFound) return } image := mux.Vars(req)["image"] if image == "" { w.WriteHeader(http.StatusNotFound) return } uploadNum := strconv.Itoa(newUpload(image)) var prefix string if *https { prefix = "https://" + serverName } else { prefix = "http://" + serverName } deets := initiateDetails{ ACIPushVersion: "0.0.1", Multipart: false, ManifestURL: prefix + "/manifest/" + uploadNum, SignatureURL: prefix + "/signature/" + uploadNum, ACIURL: prefix + "/aci/" + uploadNum, CompletedURL: prefix + "/complete/" + uploadNum, } blob, err := json.Marshal(deets) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(os.Stderr, fmt.Sprintf("%v", err)) return } _, err = w.Write(blob) if err != nil { fmt.Fprintf(os.Stderr, fmt.Sprintf("%v", err)) return } }
func uploadManifest(w http.ResponseWriter, req *http.Request) { if req.Method != "PUT" { w.WriteHeader(http.StatusNotFound) return } num, err := strconv.Atoi(mux.Vars(req)["num"]) if err != nil { w.WriteHeader(http.StatusNotFound) return } err = gotMan(num) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(os.Stderr, "%v", err) return } w.WriteHeader(http.StatusOK) }
func completeUpload(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { w.WriteHeader(http.StatusNotFound) return } num, err := strconv.Atoi(mux.Vars(req)["num"]) if err != nil { w.WriteHeader(http.StatusNotFound) return } up := getUpload(num) if up == nil { w.WriteHeader(http.StatusNotFound) return } body, err := ioutil.ReadAll(req.Body) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } fmt.Fprintf(os.Stderr, "body: %s\n", string(body)) msg := completeMsg{} err = json.Unmarshal(body, &msg) if err != nil { fmt.Fprintf(os.Stderr, "error unmarshaling json: %v", err) w.WriteHeader(http.StatusBadRequest) return } if !msg.Success { reportFailure(num, w, "client reported failure", msg.Reason) return } if !up.GotMan { reportFailure(num, w, "manifest wasn't uploaded", msg.Reason) return } if !up.GotSig { reportFailure(num, w, "signature wasn't uploaded", msg.Reason) return } if !up.GotACI { reportFailure(num, w, "ACI wasn't uploaded", msg.Reason) return } //TODO: image verification here err = finishUpload(num) if err != nil { reportFailure(num, w, "Internal Server Error", msg.Reason) return } succmsg := completeMsg{ Success: true, } blob, err := json.Marshal(succmsg) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } _, err = w.Write(blob) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } return }