From d6c3389d7cf19d9f4b41dfad15ff5f629ba7d318 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 12 Oct 2014 16:28:35 +0400 Subject: [PATCH] First steps towards /files/ API (file upload). #116 --- api/files.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ api/router.go | 8 ++++ 2 files changed, 128 insertions(+) create mode 100644 api/files.go diff --git a/api/files.go b/api/files.go new file mode 100644 index 00000000..34bfc837 --- /dev/null +++ b/api/files.go @@ -0,0 +1,120 @@ +package api + +import ( + "fmt" + "github.com/gin-gonic/gin" + "io" + "os" + "path/filepath" + "strings" +) + +func verifyDir(c *gin.Context) bool { + dir := c.Params.ByName("dir") + dir = filepath.Clean(dir) + for _, part := range strings.Split(dir, string(filepath.Separator)) { + if part == ".." || part == "." { + c.Fail(400, fmt.Errorf("wrong dir")) + return false + } + } + + return true +} + +// GET /files +func apiFilesListDirs(c *gin.Context) { + list := []string{} + + err := filepath.Walk(context.UploadPath(), func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if path == context.UploadPath() { + return nil + } + + if info.IsDir() { + list = append(list, filepath.Base(path)) + return filepath.SkipDir + } + + return nil + }) + + if err != nil && !os.IsNotExist(err) { + c.Fail(400, err) + return + } + + c.JSON(200, list) +} + +// POST /files/:dir/ +func apiFilesUpload(c *gin.Context) { + if !verifyDir(c) { + return + } + + path := filepath.Join(context.UploadPath(), c.Params.ByName("dir")) + err := os.MkdirAll(path, 0777) + + if err != nil { + c.Fail(500, err) + return + } + + err = c.Request.ParseMultipartForm(10 * 1024 * 1024) + if err != nil { + c.Fail(400, err) + return + } + + stored := []string{} + + for _, files := range c.Request.MultipartForm.File { + for _, file := range files { + src, err := file.Open() + if err != nil { + c.Fail(500, err) + return + } + defer src.Close() + + destPath := filepath.Join(path, filepath.Base(file.Filename)) + dst, err := os.Create(destPath) + if err != nil { + c.Fail(500, err) + return + } + defer dst.Close() + + _, err = io.Copy(dst, src) + if err != nil { + c.Fail(500, err) + return + } + + stored = append(stored, filepath.Join(c.Params.ByName("dir"), filepath.Base(file.Filename))) + } + } + + c.JSON(200, stored) + +} + +// GET /files/:dir +func apiFilesListFiles(c *gin.Context) { + +} + +// DELETE /files/:dir +func apiFilesDeleteDir(c *gin.Context) { + +} + +// DELETE /files/:dir/:name +func apiFilesDeleteFile(c *gin.Context) { + +} diff --git a/api/router.go b/api/router.go index 4a2bd47c..658290e7 100644 --- a/api/router.go +++ b/api/router.go @@ -27,5 +27,13 @@ func Router(c *ctx.AptlyContext) http.Handler { root.POST("/repos/:name/packages", apiReposPackagesAdd) } + { + root.GET("/files", apiFilesListDirs) + root.POST("/files/:dir", apiFilesUpload) + root.GET("/files/:dir", apiFilesListFiles) + root.DELETE("/files/:dir", apiFilesDeleteDir) + root.DELETE("/files/:dir/:name", apiFilesDeleteFile) + } + return router }