diff --git a/cmd/event-notification.go b/cmd/event-notification.go
index cba7e4ab2..9f56c4968 100644
--- a/cmd/event-notification.go
+++ b/cmd/event-notification.go
@@ -225,7 +225,11 @@ func (args eventArgs) ToEvent(escape bool) event.Event {
},
}
- if args.EventName != event.ObjectRemovedDelete && args.EventName != event.ObjectRemovedDeleteMarkerCreated {
+ isRemovedEvent := args.EventName == event.ObjectRemovedDelete ||
+ args.EventName == event.ObjectRemovedDeleteMarkerCreated ||
+ args.EventName == event.ObjectRemovedNoOP
+
+ if !isRemovedEvent {
newEvent.S3.Object.ETag = args.Object.ETag
newEvent.S3.Object.Size = args.Object.Size
newEvent.S3.Object.ContentType = args.Object.ContentType
diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go
index 4cfbc1316..5db412d92 100644
--- a/cmd/object-handlers.go
+++ b/cmd/object-handlers.go
@@ -2891,6 +2891,18 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http.
return
}
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
+ // Send an event when the object is not found
+ objInfo.Name = object
+ objInfo.VersionID = opts.VersionID
+ sendEvent(eventArgs{
+ EventName: event.ObjectRemovedNoOP,
+ BucketName: bucket,
+ Object: objInfo,
+ ReqParams: extractReqParams(r),
+ RespElements: extractRespElements(w),
+ UserAgent: r.UserAgent(),
+ Host: handlers.GetSourceIP(r),
+ })
writeSuccessNoContent(w)
return
}
diff --git a/internal/event/name.go b/internal/event/name.go
index 966c7e7b0..3f13cad82 100644
--- a/internal/event/name.go
+++ b/internal/event/name.go
@@ -47,6 +47,7 @@ const (
ObjectCreatedDeleteTagging
ObjectRemovedDelete
ObjectRemovedDeleteMarkerCreated
+ ObjectRemovedNoOP
BucketCreated
BucketRemoved
ObjectReplicationFailed
@@ -98,6 +99,7 @@ func (name Name) Expand() []Name {
return []Name{
ObjectRemovedDelete,
ObjectRemovedDeleteMarkerCreated,
+ ObjectRemovedNoOP,
}
case ObjectReplicationAll:
return []Name{
@@ -189,6 +191,8 @@ func (name Name) String() string {
return "s3:ObjectRemoved:Delete"
case ObjectRemovedDeleteMarkerCreated:
return "s3:ObjectRemoved:DeleteMarkerCreated"
+ case ObjectRemovedNoOP:
+ return "s3:ObjectRemoved:NoOP"
case ObjectReplicationAll:
return "s3:Replication:*"
case ObjectReplicationFailed:
@@ -307,6 +311,8 @@ func ParseName(s string) (Name, error) {
return ObjectRemovedDelete, nil
case "s3:ObjectRemoved:DeleteMarkerCreated":
return ObjectRemovedDeleteMarkerCreated, nil
+ case "s3:ObjectRemoved:NoOP":
+ return ObjectRemovedNoOP, nil
case "s3:Replication:*":
return ObjectReplicationAll, nil
case "s3:Replication:OperationFailedReplication":
diff --git a/internal/event/name_test.go b/internal/event/name_test.go
index 0e0f748b6..130ff7036 100644
--- a/internal/event/name_test.go
+++ b/internal/event/name_test.go
@@ -36,7 +36,7 @@ func TestNameExpand(t *testing.T) {
ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, ObjectCreatedPost, ObjectCreatedPut,
ObjectCreatedPutRetention, ObjectCreatedPutLegalHold, ObjectCreatedPutTagging, ObjectCreatedDeleteTagging,
}},
- {ObjectRemovedAll, []Name{ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated}},
+ {ObjectRemovedAll, []Name{ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated, ObjectRemovedNoOP}},
{ObjectAccessedHead, []Name{ObjectAccessedHead}},
}
@@ -68,6 +68,7 @@ func TestNameString(t *testing.T) {
{ObjectCreatedPut, "s3:ObjectCreated:Put"},
{ObjectRemovedAll, "s3:ObjectRemoved:*"},
{ObjectRemovedDelete, "s3:ObjectRemoved:Delete"},
+ {ObjectRemovedNoOP, "s3:ObjectRemoved:NoOP"},
{ObjectCreatedPutRetention, "s3:ObjectCreated:PutRetention"},
{ObjectCreatedPutLegalHold, "s3:ObjectCreated:PutLegalHold"},
{ObjectAccessedGetRetention, "s3:ObjectAccessed:GetRetention"},
@@ -95,6 +96,7 @@ func TestNameMarshalXML(t *testing.T) {
}{
{ObjectAccessedAll, []byte("s3:ObjectAccessed:*"), false},
{ObjectRemovedDelete, []byte("s3:ObjectRemoved:Delete"), false},
+ {ObjectRemovedNoOP, []byte("s3:ObjectRemoved:NoOP"), false},
{blankName, []byte(""), false},
}
@@ -124,6 +126,7 @@ func TestNameUnmarshalXML(t *testing.T) {
}{
{[]byte("s3:ObjectAccessed:*"), ObjectAccessedAll, false},
{[]byte("s3:ObjectRemoved:Delete"), ObjectRemovedDelete, false},
+ {[]byte("s3:ObjectRemoved:NoOP"), ObjectRemovedNoOP, false},
{[]byte(""), blankName, true},
}
@@ -154,6 +157,7 @@ func TestNameMarshalJSON(t *testing.T) {
}{
{ObjectAccessedAll, []byte(`"s3:ObjectAccessed:*"`), false},
{ObjectRemovedDelete, []byte(`"s3:ObjectRemoved:Delete"`), false},
+ {ObjectRemovedNoOP, []byte(`"s3:ObjectRemoved:NoOP"`), false},
{blankName, []byte(`""`), false},
}
@@ -183,6 +187,7 @@ func TestNameUnmarshalJSON(t *testing.T) {
}{
{[]byte(`"s3:ObjectAccessed:*"`), ObjectAccessedAll, false},
{[]byte(`"s3:ObjectRemoved:Delete"`), ObjectRemovedDelete, false},
+ {[]byte(`"s3:ObjectRemoved:NoOP"`), ObjectRemovedNoOP, false},
{[]byte(`""`), blankName, true},
}
@@ -213,6 +218,7 @@ func TestParseName(t *testing.T) {
}{
{"s3:ObjectAccessed:*", ObjectAccessedAll, false},
{"s3:ObjectRemoved:Delete", ObjectRemovedDelete, false},
+ {"s3:ObjectRemoved:NoOP", ObjectRemovedNoOP, false},
{"", blankName, true},
}