diff --git a/docs/apis.md b/docs/apis.md index 0784434..0857335 100644 --- a/docs/apis.md +++ b/docs/apis.md @@ -209,4 +209,28 @@ GET /default/ ``` GET /default/?restype=directory +``` + +### Upload a file + +``` +POST /default/ +``` + +The request will be rejected either when the directory does not exist or when the file already exists + +**Request content type** + +form-data + +**Request body** + +|Name|Description| +|-|-| +|file|Required. File| + +**Response status** + +``` +200 OK ``` \ No newline at end of file diff --git a/pkg/routes/api.go b/pkg/routes/api.go index 90b6b53..92fcff8 100644 --- a/pkg/routes/api.go +++ b/pkg/routes/api.go @@ -12,11 +12,14 @@ import ( var Router = gin.Default() func init() { + // Set a lower memory limit for multipart forms (default is 32 MiB) + Router.MaxMultipartMemory = 8 << 20 // 8 MiB v1 := Router.Group("/api/v1") { v1.GET("/default/*contentPath", v1handlers.HandleGet) v1.PUT("/default/*contentPath", v1handlers.HandlePut) v1.DELETE("/default/*contentPath", v1handlers.HandleDelete) v1.PATCH("/default/*contentPath", v1handlers.HandlePatch) + v1.POST("/default/*contentPath", v1handlers.HandlePost) } } diff --git a/pkg/v1handlers/post.go b/pkg/v1handlers/post.go new file mode 100644 index 0000000..d544788 --- /dev/null +++ b/pkg/v1handlers/post.go @@ -0,0 +1,61 @@ +package v1handlers + +import ( + "fmt" + "log" + "net/http" + "os" + "path" + + "github.com/gin-gonic/gin" +) + +func HandlePost(c *gin.Context) { + paramContentPath := c.Param("contentPath") + + if err := EnsureSecurePaths(paramContentPath); err != nil { + log.Println("checkpath failed:", err) + c.String(http.StatusBadRequest, err.Error()) + return + } + + fullDirPath := path.Join(MountedVolume, paramContentPath) + + dirInfo, err := os.Stat(fullDirPath) + if err != nil || !(dirInfo.IsDir()) { + c.String(http.StatusBadRequest, fmt.Sprintf("no such directory %s", paramContentPath)) + return + } + + // if there is other post request, + // it should be processed here + handleUpload(c) + return +} + +func handleUpload(c *gin.Context) { + paramContentPath := c.Param("contentPath") + + // upload file + // TODO: upload directory + file, err := c.FormFile("file") + if err != nil { + c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error())) + return + } + + dst := path.Join(MountedVolume, paramContentPath, file.Filename) + + if _, err := os.Stat(dst); !os.IsNotExist(err) { + errMsg := fmt.Sprintf("%s already exists", file.Filename) + c.String(http.StatusBadRequest, errMsg) + return + } + + if err := c.SaveUploadedFile(file, dst); err != nil { + c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error())) + return + } + + c.String(http.StatusOK, "file uploaded") +}