diff --git a/backend/posix/posix.go b/backend/posix/posix.go index 8d49fc7..157c26d 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -878,6 +878,8 @@ func (p *Posix) UploadPartCopy(upi *s3.UploadPartCopyInput) (s3response.CopyObje } func (p *Posix) PutObject(po *s3.PutObjectInput) (string, error) { + tagsStr := getString(po.Tagging) + tags := make(map[string]string) _, err := os.Stat(*po.Bucket) if errors.Is(err, fs.ErrNotExist) { return "", s3err.GetAPIError(s3err.ErrNoSuchBucket) @@ -886,6 +888,17 @@ func (p *Posix) PutObject(po *s3.PutObjectInput) (string, error) { return "", fmt.Errorf("stat bucket: %w", err) } + if tagsStr != "" { + tagParts := strings.Split(tagsStr, "&") + for _, prt := range tagParts { + p := strings.Split(prt, "=") + if len(p) != 2 { + return "", s3err.GetAPIError(s3err.ErrInvalidTag) + } + tags[p[0]] = p[1] + } + } + name := filepath.Join(*po.Bucket, *po.Key) if strings.HasSuffix(*po.Key, "/") { @@ -936,6 +949,13 @@ func (p *Posix) PutObject(po *s3.PutObjectInput) (string, error) { xattr.Set(name, "user."+k, []byte(v)) } + if tagsStr != "" { + err := p.SetTags(*po.Bucket, *po.Key, tags) + if err != nil { + return "", err + } + } + dataSum := hash.Sum(nil) etag := hex.EncodeToString(dataSum[:]) xattr.Set(name, etagkey, []byte(etag)) @@ -1633,3 +1653,10 @@ func isNoAttr(err error) bool { } return false } + +func getString(str *string) string { + if str == nil { + return "" + } + return *str +} diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index acfd9a2..074fbb3 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -377,6 +377,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { uploadId := ctx.Query("uploadId") access := ctx.Locals("access").(string) isRoot := ctx.Locals("isRoot").(bool) + tagging := ctx.Get("x-amz-tagging") // Copy source headers copySource := ctx.Get("X-Amz-Copy-Source") @@ -617,6 +618,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { ContentLength: contentLength, Metadata: metadata, Body: bytes.NewReader(ctx.Request().Body()), + Tagging: &tagging, }) ctx.Response().Header.Set("ETag", etag) return SendResponse(ctx, err, &MetaOpts{