From 0b92d9457004797120d0fc025f9fba9a04cacbeb Mon Sep 17 00:00:00 2001 From: Ramires Viana <59319979+ramiresviana@users.noreply.github.com> Date: Wed, 10 Mar 2021 13:32:11 +0000 Subject: [PATCH] chore: split POST method on resource http handler --- http/http.go | 4 +- http/resource.go | 102 ++++++++++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/http/http.go b/http/http.go index 135fa05c..47073653 100644 --- a/http/http.go +++ b/http/http.go @@ -54,8 +54,8 @@ func NewHandler( api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET") api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE") - api.PathPrefix("/resources").Handler(monkey(resourcePostPutHandler, "/api/resources")).Methods("POST") - api.PathPrefix("/resources").Handler(monkey(resourcePostPutHandler, "/api/resources")).Methods("PUT") + api.PathPrefix("/resources").Handler(monkey(resourcePostHandler, "/api/resources")).Methods("POST") + api.PathPrefix("/resources").Handler(monkey(resourcePutHandler, "/api/resources")).Methods("PUT") api.PathPrefix("/resources").Handler(monkey(resourcePatchHandler, "/api/resources")).Methods("PATCH") api.Path("/shares").Handler(monkey(shareListHandler, "/api/shares")).Methods("GET") diff --git a/http/resource.go b/http/resource.go index 9d036dca..16be5d89 100644 --- a/http/resource.go +++ b/http/resource.go @@ -90,12 +90,8 @@ func resourceDeleteHandler(fileCache FileCache) handleFunc { }) } -var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { - if !d.user.Perm.Create && r.Method == http.MethodPost { - return http.StatusForbidden, nil - } - - if !d.user.Perm.Modify && r.Method == http.MethodPut { +var resourcePostHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { + if !d.user.Perm.Create { return http.StatusForbidden, nil } @@ -103,55 +99,54 @@ var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Reques _, _ = io.Copy(ioutil.Discard, r.Body) }() - // For directories, only allow POST for creation. + // Directories creation on POST. if strings.HasSuffix(r.URL.Path, "/") { - if r.Method == http.MethodPut { - return http.StatusMethodNotAllowed, nil - } - err := d.user.Fs.MkdirAll(r.URL.Path, 0775) return errToStatus(err), err } - if r.Method == http.MethodPost && r.URL.Query().Get("override") != "true" { + if r.URL.Query().Get("override") != "true" { if _, err := d.user.Fs.Stat(r.URL.Path); err == nil { return http.StatusConflict, nil } } - action := "upload" - if r.Method == http.MethodPut { - action = "save" - } - err := d.RunHook(func() error { - dir, _ := path.Split(r.URL.Path) - err := d.user.Fs.MkdirAll(dir, 0775) - if err != nil { - return err - } - - file, err := d.user.Fs.OpenFile(r.URL.Path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) - if err != nil { - return err - } - defer file.Close() - - _, err = io.Copy(file, r.Body) - if err != nil { - return err - } - - // Gets the info about the file. - info, err := file.Stat() - if err != nil { - return err - } + info, _ := writeFile(d.user.Fs, r.URL.Path, r.Body) etag := fmt.Sprintf(`"%x%x"`, info.ModTime().UnixNano(), info.Size()) w.Header().Set("ETag", etag) return nil - }, action, r.URL.Path, "", d.user) + }, "upload", r.URL.Path, "", d.user) + + if err != nil { + _ = d.user.Fs.RemoveAll(r.URL.Path) + } + + return errToStatus(err), err +}) + +var resourcePutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { + if !d.user.Perm.Modify { + return http.StatusForbidden, nil + } + + defer func() { + _, _ = io.Copy(ioutil.Discard, r.Body) + }() + + // Only allow PUT for files. + if strings.HasSuffix(r.URL.Path, "/") { + return http.StatusMethodNotAllowed, nil + } + + err := d.RunHook(func() error { + info, _ := writeFile(d.user.Fs, r.URL.Path, r.Body) + + etag := fmt.Sprintf(`"%x%x"`, info.ModTime().UnixNano(), info.Size()) + w.Header().Set("ETag", etag) + return nil + }, "save", r.URL.Path, "", d.user) if err != nil { _ = d.user.Fs.RemoveAll(r.URL.Path) @@ -242,3 +237,30 @@ func addVersionSuffix(source string, fs afero.Fs) string { return source } + +func writeFile(fs afero.Fs, dst string, in io.Reader) (os.FileInfo, error) { + dir, _ := path.Split(dst) + err := fs.MkdirAll(dir, 0775) + if err != nil { + return nil, err + } + + file, err := fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) + if err != nil { + return nil, err + } + defer file.Close() + + _, err = io.Copy(file, in) + if err != nil { + return nil, err + } + + // Gets the info about the file. + info, err := file.Stat() + if err != nil { + return nil, err + } + + return info, nil +}