// PUT: /node/{id} -> multipart-form func (cr *NodeController) Update(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } // Gather query params query := &Query{list: cx.Request.URL.Query()} // Fake public user if u == nil { u = &user.User{Uuid: ""} } node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. log.Error("Err@node_Update:LoadNode: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } if query.Has("index") { if !node.HasFile() { cx.RespondWithErrorMessage("node file empty", http.StatusBadRequest) return } if query.Value("index") == "bai" { //bam index is created by the command-line tool samtools if ext := node.FileExt(); ext == ".bam" { if err := CreateBamIndex(node.FilePath()); err != nil { cx.RespondWithErrorMessage("Error while creating bam index", http.StatusBadRequest) return } return } else { cx.RespondWithErrorMessage("Index type bai requires .bam file", http.StatusBadRequest) return } } newIndexer := indexer.Indexer(query.Value("index")) f, _ := os.Open(node.FilePath()) defer f.Close() idxer := newIndexer(f) err := idxer.Create() if err != nil { log.Error("err " + err.Error()) } err = idxer.Dump(node.IndexPath() + "/record") if err != nil { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } else { cx.RespondWithOK() return } } else { params, files, err := ParseMultipartForm(cx.Request) if err != nil { log.Error("err " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } err = node.Update(params, files) if err != nil { errors := []string{e.FileImut, e.AttrImut, "parts cannot be less than 1"} for e := range errors { if err.Error() == errors[e] { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } } log.Error("err " + err.Error()) cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } cx.RespondWithData(node) } return }
// GET: /node/{id} // ToDo: clean up this function. About to get unmanageable func (cr *NodeController) Read(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil { // No Auth is not damning. Other errors are probably a dead db connection if err.Error() != e.NoAuth { if err.Error() == e.MongoDocNotFound { cx.RespondWithErrorMessage("Invalid username or password", http.StatusBadRequest) return } else { fmt.Println("Error at Auth:", err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } } // Fake public user if u == nil { u = &user.User{Uuid: ""} } // Gather query params query := &Query{list: cx.Request.URL.Query()} var fFunc filter.FilterFunc = nil if query.Has("filter") { if filter.Has(query.Value("filter")) { fFunc = filter.Filter(query.Value("filter")) } } // Load node and handle user unauthorized node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { fmt.Println("Unauthorized") cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. fmt.Println("Err@node_Read:LoadNode:", err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } // Switch though param flags // ?download=1 if query.Has("download") { if !node.HasFile() { cx.RespondWithErrorMessage("node file not found", http.StatusBadRequest) return } //_, chunksize := // ?index=foo if query.Has("index") { // if forgot ?part=N if !query.Has("part") { cx.RespondWithErrorMessage("Index parameter requires part parameter", http.StatusBadRequest) return } // open file r, err := os.Open(node.DataPath()) defer r.Close() if err != nil { fmt.Println("Err@node_Read:Open:", err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } // load index idx, err := node.Index(query.Value("index")) if err != nil { cx.RespondWithErrorMessage("Invalid index", http.StatusBadRequest) return } if idx.Type() == "virtual" { csize := int64(1048576) if query.Has("chunksize") { csize, err = strconv.ParseInt(query.Value("chunksize"), 10, 64) if err != nil { cx.RespondWithErrorMessage("Invalid chunksize", http.StatusBadRequest) return } } idx.Set(map[string]interface{}{"ChunkSize": csize}) } var size int64 = 0 s := &streamer{rs: []io.ReadCloser{}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, filter: fFunc} for _, p := range query.List("part") { pos, length, err := idx.Part(p) if err != nil { cx.RespondWithErrorMessage("Invalid index part", http.StatusBadRequest) return } size += length s.rs = append(s.rs, NewSectionReaderCloser(r, pos, length)) } s.size = size err = s.stream() if err != nil { // fix fmt.Println("err", err.Error()) } } else { nf, err := os.Open(node.DataPath()) if err != nil { // File not found or some sort of file read error. // Probably deserves more checking fmt.Println("err", err.Error()) cx.RespondWithError(http.StatusBadRequest) return } s := &streamer{rs: []io.ReadCloser{nf}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, size: node.File.Size, filter: fFunc} err = s.stream() if err != nil { // fix fmt.Println("err", err.Error()) } } return } else if query.Has("pipe") { cx.RespondWithError(http.StatusNotImplemented) } else if query.Has("list") { cx.RespondWithError(http.StatusNotImplemented) } else { // Base case respond with node in json cx.RespondWithData(node) } }
// GET: /node/{id} // ToDo: clean up this function. About to get unmanageable func (cr *NodeController) Read(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } // Fake public user if u == nil { if conf.ANON_READ { u = &user.User{Uuid: ""} } else { cx.RespondWithErrorMessage(e.NoAuth, http.StatusUnauthorized) return } } // Gather query params query := &Query{list: cx.Request.URL.Query()} var fFunc filter.FilterFunc = nil if query.Has("filter") { if filter.Has(query.Value("filter")) { fFunc = filter.Filter(query.Value("filter")) } } // Load node and handle user unauthorized node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. log.Error("Err@node_Read:LoadNode: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } // Switch though param flags // ?download=1 if query.Has("download") { if !node.HasFile() { cx.RespondWithErrorMessage("File not found", http.StatusBadRequest) return } //_, chunksize := // ?index=foo if query.Has("index") { //handling bam file if query.Value("index") == "bai" { s := &streamer{rs: []store.SectionReader{}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, size: node.File.Size, filter: fFunc} var region string if query.Has("region") { //retrieve alingments overlapped with specified region region = query.Value("region") } argv, err := ParseSamtoolsArgs(query) if err != nil { cx.RespondWithErrorMessage("Invaid args in query url", http.StatusBadRequest) return } err = s.stream_samtools(node.FilePath(), region, argv...) if err != nil { cx.RespondWithErrorMessage("error while involking samtools", http.StatusBadRequest) return } return } // if forgot ?part=N if !query.Has("part") { cx.RespondWithErrorMessage("Index parameter requires part parameter", http.StatusBadRequest) return } // open file r, err := node.FileReader() if err != nil { log.Error("Err@node_Read:Open: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } // load index idx, err := node.Index(query.Value("index")) if err != nil { cx.RespondWithErrorMessage("Invalid index", http.StatusBadRequest) return } if idx.Type() == "virtual" { csize := int64(1048576) if query.Has("chunksize") { csize, err = strconv.ParseInt(query.Value("chunksize"), 10, 64) if err != nil { cx.RespondWithErrorMessage("Invalid chunksize", http.StatusBadRequest) return } } idx.Set(map[string]interface{}{"ChunkSize": csize}) } var size int64 = 0 s := &streamer{rs: []store.SectionReader{}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, filter: fFunc} for _, p := range query.List("part") { pos, length, err := idx.Part(p) if err != nil { cx.RespondWithErrorMessage("Invalid index part", http.StatusBadRequest) return } size += length s.rs = append(s.rs, io.NewSectionReader(r, pos, length)) } s.size = size err = s.stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) log.Error("err: " + err.Error()) } } else { //!query.Has("index") nf, err := node.FileReader() if err != nil { // File not found or some sort of file read error. // Probably deserves more checking log.Error("err " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } s := &streamer{rs: []store.SectionReader{nf}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, size: node.File.Size, filter: fFunc} err = s.stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) log.Error("err " + err.Error()) } } return } else if query.Has("pipe") { cx.RespondWithError(http.StatusNotImplemented) } else if query.Has("list") { cx.RespondWithError(http.StatusNotImplemented) } else { // Base case respond with node in json cx.RespondWithData(node) } }
// PUT: /node/{id} -> multipart-form func (cr *NodeController) Update(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil { // No Auth is not damning. Other errors are probably a dead db connection if err.Error() != e.NoAuth { if err.Error() == e.MongoDocNotFound { cx.RespondWithErrorMessage("Invalid username or password", http.StatusBadRequest) return } else { fmt.Println("Error at Auth:", err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } } // Gather query params query := &Query{list: cx.Request.URL.Query()} // Fake public user if u == nil { u = &user.User{Uuid: ""} } node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { fmt.Println("Unauthorized") cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. fmt.Println("Err@node_Update:LoadNode:", err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } if query.Has("index") { if !node.HasFile() { cx.RespondWithErrorMessage("node file empty", http.StatusBadRequest) return } newIndexer := indexer.Indexer(query.Value("index")) f, _ := os.Open(node.DataPath()) defer f.Close() idxer := newIndexer(f) err := idxer.Create() if err != nil { fmt.Println(err.Error()) } err = idxer.Dump(node.IndexPath() + "/record") if err != nil { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } else { cx.RespondWithOK() return } } else { params, files, err := ParseMultipartForm(cx.Request) if err != nil { fmt.Println("err", err.Error()) cx.RespondWithError(http.StatusBadRequest) return } err = node.Update(params, files) if err != nil { errors := []string{"node file already set and is immutable", "node file immutable", "node attributes immutable", "node part already exists and is immutable"} for e := range errors { if err.Error() == errors[e] { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } } fmt.Println("err", err.Error()) cx.RespondWithError(http.StatusBadRequest) return } cx.RespondWithData(node) } return }