func handleBatchRemove(req *http.Request, storage blobserver.Storage) (interface{}, error) { res := new(protocol.RemoveResponse) n := 0 toRemove := make([]blob.Ref, 0) for { n++ if n > maxRemovesPerRequest { return nil, newRateLimitError(maxRemovesPerRequest) } key := fmt.Sprintf("blob%v", n) value := req.FormValue(key) ref, ok := blob.Parse(value) if !ok { break } toRemove = append(toRemove, ref) } err := storage.RemoveBlobs(toRemove) if err != nil { log.Errorf("Server error during remove: %v", err) return nil, newHTTPError("Server error", http.StatusInternalServerError) } res.Removed = toRemove return res, nil }
func handleRemove(req *http.Request, storage blobserver.Storage) (interface{}, error) { res := new(protocol.RemoveResponse) vars := mux.Vars(req) ref, ok := blob.Parse(vars["blobRef"]) if !ok { return nil, newHTTPError("Invalid blob ref", http.StatusBadRequest) } toRemove := []blob.Ref{ref} err := storage.RemoveBlobs(toRemove) if err != nil { log.Errorf("Server error during remove: %v", err) return nil, newHTTPError("Server error", http.StatusInternalServerError) } res.Removed = toRemove return res, nil }
func handleMultiPartUpload(req *http.Request, blobReceiver blobserver.Storage) (interface{}, error) { res := new(protocol.UploadResponse) receivedBlobs := make([]blob.SizedRef, 0, 4) multipart, err := req.MultipartReader() if err != nil { return nil, newHTTPError(fmt.Sprintf("Expected multipart/form-data POST request; %v", err), http.StatusBadRequest) } useFilename := false req.ParseForm() if req.FormValue("use-filename") != "" { useFilename = true } for { mimePart, err := multipart.NextPart() if err == io.EOF { break } if err != nil { return nil, newHTTPError(fmt.Sprintf("Error reading multipart section: %v", err), http.StatusBadRequest) } contentDisposition, _, err := mime.ParseMediaType(mimePart.Header.Get("Content-Disposition")) if err != nil { return nil, newHTTPError("Invalid Content-Disposition", http.StatusBadRequest) } if contentDisposition != "form-data" { return nil, newHTTPError(fmt.Sprintf("Expected Content-Disposition of \"form-data\"; got %q", contentDisposition), http.StatusBadRequest) } var ref blob.Ref var tooBig int64 = blobserver.MaxBlobSize + 1 var readBytes int64 filename := mimePart.FileName() log.Println("filename:", filename) if useFilename { log.Println("Use filename") ref = blob.NewRefFilename(filename) } else { ref = blob.NewRef(filename) } blobGot, err := blobReceiver.ReceiveBlob(ref, &readerutil.CountingReader{ Reader: io.LimitReader(mimePart, tooBig), N: &readBytes, }) if readBytes == tooBig { err = fmt.Errorf("blob over the limit of %d bytes", blobserver.MaxBlobSize) } if err != nil { var errmsg string if log.Severity >= log.LevelInfo { errmsg = fmt.Sprintf("Error receiving blob (read bytes: %d) %v: %v\n", readBytes, ref, err) } else { errmsg = fmt.Sprintf("Error receiving blob: %v\n", err) } return nil, newHTTPError(errmsg, http.StatusInternalServerError) } log.Printf("Received blob %v\n", blobGot) receivedBlobs = append(receivedBlobs, blobGot) } for _, got := range receivedBlobs { rv := protocol.RefInfo{ Ref: got.Ref, Size: uint32(got.Size), } if h := got.Hash(); h != nil { rv.MD5 = hex.EncodeToString(h.Sum(nil)) } res.Received = append(res.Received, rv) } return res, nil }