diff --git a/api/handler/head.go b/api/handler/head.go index 4e494cb80..9864d79ea 100644 --- a/api/handler/head.go +++ b/api/handler/head.go @@ -47,7 +47,7 @@ func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { h.logAndSendError(w, "could not fetch object info", reqInfo, err) return } - tagSet, err := h.obj.GetObjectTagging(r.Context(), inf) + tagSet, err := h.obj.GetObjectTagging(r.Context(), info) if err != nil && !errors.IsS3Error(err, errors.ErrNoSuchKey) { h.logAndSendError(w, "could not get object tag set", reqInfo, err) return diff --git a/api/handler/tagging.go b/api/handler/tagging.go index bb1134638..72689733c 100644 --- a/api/handler/tagging.go +++ b/api/handler/tagging.go @@ -106,6 +106,28 @@ func checkTagSet(tagSet []Tag) error { return nil } +func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { + reqInfo := api.GetReqInfo(r.Context()) + + p := &layer.HeadObjectParams{ + Bucket: reqInfo.BucketName, + Object: reqInfo.ObjectName, + VersionID: reqInfo.URL.Query().Get("versionId"), + } + + objInfo, err := h.obj.GetObjectInfo(r.Context(), p) + if err != nil { + h.logAndSendError(w, "could not get object info", reqInfo, err) + return + } + + if err = h.obj.DeleteObjectTagging(r.Context(), objInfo); err != nil { + h.logAndSendError(w, "could not delete object tagging", reqInfo, err) + return + } + w.WriteHeader(http.StatusNoContent) +} + func checkTag(tag Tag) error { if len(tag.Key) < 1 || len(tag.Key) > keyTagMaxLength { return errors.GetAPIError(errors.ErrInvalidTag) diff --git a/api/handler/unimplemented.go b/api/handler/unimplemented.go index a10583b66..61cbe3637 100644 --- a/api/handler/unimplemented.go +++ b/api/handler/unimplemented.go @@ -31,10 +31,6 @@ func (h *handler) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Req h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented)) } -func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { - h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented)) -} - func (h *handler) SelectObjectContentHandler(w http.ResponseWriter, r *http.Request) { h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented)) } diff --git a/api/layer/layer.go b/api/layer/layer.go index dcee78625..88b66d086 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -8,6 +8,7 @@ import ( "io" "net/url" "strconv" + "strings" "time" "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" @@ -174,6 +175,7 @@ type ( ListObjectVersions(ctx context.Context, p *ListObjectVersionsParams) (*ListObjectVersionsInfo, error) DeleteObjects(ctx context.Context, bucket string, objects []*VersionedObject) []error + DeleteObjectTagging(ctx context.Context, p *ObjectInfo) error } ) @@ -374,7 +376,7 @@ func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*ObjectInfo, // GetObjectTagging from storage. func (n *layer) GetObjectTagging(ctx context.Context, oi *ObjectInfo) (map[string]string, error) { - bktInfo := &BucketInfo{ + bktInfo := &cache.BucketInfo{ Name: oi.Bucket, CID: oi.CID(), Owner: oi.Owner, @@ -413,6 +415,19 @@ func (n *layer) PutObjectTagging(ctx context.Context, p *PutTaggingParams) error return nil } +// DeleteObjectTagging from storage. +func (n *layer) DeleteObjectTagging(ctx context.Context, p *ObjectInfo) error { + oid, err := n.objectFindID(ctx, &findParams{cid: p.CID(), attr: objectSystemAttributeName, val: p.TagsObject()}) + if err != nil { + if errors.IsS3Error(err, errors.ErrNoSuchKey) { + return nil + } + return err + } + + return n.objectDelete(ctx, p.CID(), oid) +} + func (n *layer) putSystemObject(ctx context.Context, bktInfo *cache.BucketInfo, objName string, metadata map[string]string, prefix string) (*object.ID, error) { oldOID, err := n.objectFindID(ctx, &findParams{cid: bktInfo.CID, attr: objectSystemAttributeName, val: objName}) if err != nil && !errors.IsS3Error(err, errors.ErrNoSuchKey) { @@ -465,7 +480,7 @@ func (n *layer) putSystemObject(ctx context.Context, bktInfo *cache.BucketInfo, return oid, nil } -func (n *layer) getSystemObject(ctx context.Context, bkt *BucketInfo, objName string) (*ObjectInfo, error) { +func (n *layer) getSystemObject(ctx context.Context, bkt *cache.BucketInfo, objName string) (*ObjectInfo, error) { oid, err := n.objectFindID(ctx, &findParams{cid: bkt.CID, attr: objectSystemAttributeName, val: objName}) if err != nil { return nil, err @@ -546,6 +561,9 @@ func (n *layer) deleteObject(ctx context.Context, bkt *cache.BucketInfo, obj *Ve if err = n.objectDelete(ctx, bkt.CID, id); err != nil { return err } + if err = n.DeleteObjectTagging(ctx, &ObjectInfo{id: id, bucketID: bkt.CID, Name: obj.Name}); err != nil { + return err + } } return nil diff --git a/api/layer/versioning.go b/api/layer/versioning.go index fac349402..b0d0f7a96 100644 --- a/api/layer/versioning.go +++ b/api/layer/versioning.go @@ -112,6 +112,15 @@ func (v *objectVersions) getDelHeader() string { return strings.Join(v.delList, ",") } +func (v *objectVersions) getVersion(oid *object.ID) *ObjectInfo { + for _, version := range v.objects { + if version.ID() == oid { + return version + } + } + return nil +} + func (n *layer) PutBucketVersioning(ctx context.Context, p *PutVersioningParams) (*ObjectInfo, error) { bucketInfo, err := n.GetBucketInfo(ctx, p.Bucket) if err != nil { diff --git a/docs/aws_s3_compat.md b/docs/aws_s3_compat.md index 31a68ae3f..5ba5094df 100644 --- a/docs/aws_s3_compat.md +++ b/docs/aws_s3_compat.md @@ -68,7 +68,7 @@ Should be supported soon. | | Method | Comments | |----|---------------------|----------| -| 🔴 | DeleteObjectTagging | | +| 🟢 | DeleteObjectTagging | | | 🟢 | GetObjectTagging | | | 🟢 | PutObjectTagging | |