@ -54,15 +54,17 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque
if versionId != "" {
// Delete specific version (same for both enabled and suspended)
// Check object lock permissions before deleting specific version
// The returned entry is reused to avoid duplicate filer lookups
governanceBypassAllowed := s3a . evaluateGovernanceBypassRequest ( r , bucket , object )
if _ , lockErr := s3a . enforceObjectLockProtections ( r , bucket , object , versionId , governanceBypassAllowed ) ; lockErr != nil {
prefetchedEntry , lockErr := s3a . enforceObjectLockProtections ( r , bucket , object , versionId , governanceBypassAllowed )
if lockErr != nil {
glog . V ( 2 ) . Infof ( "DeleteObjectHandler: object lock check failed for %s/%s: %v" , bucket , object , lockErr )
s3err . WriteErrorResponse ( w , r , s3err . ErrAccessDenied )
return
}
// Delete specific version
err := s3a . deleteSpecificObjectVersion ( bucket , object , versionId )
// Delete specific version, passing prefetched entry to avoid duplicate lookup
err := s3a . deleteSpecificObjectVersion ( bucket , object , versionId , prefetchedEntry )
if err != nil {
glog . Errorf ( "Failed to delete specific version %s: %v" , versionId , err )
s3err . WriteErrorResponse ( w , r , s3err . ErrInternalError )
@ -92,15 +94,17 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque
glog . V ( 2 ) . Infof ( "DeleteObjectHandler: deleting null version for suspended versioning %s/%s" , bucket , object )
// Check object lock permissions before deleting "null" version
// The returned entry is reused to avoid duplicate filer lookups
governanceBypassAllowed := s3a . evaluateGovernanceBypassRequest ( r , bucket , object )
if _ , lockErr := s3a . enforceObjectLockProtections ( r , bucket , object , "null" , governanceBypassAllowed ) ; lockErr != nil {
prefetchedEntry , lockErr := s3a . enforceObjectLockProtections ( r , bucket , object , "null" , governanceBypassAllowed )
if lockErr != nil {
glog . V ( 2 ) . Infof ( "DeleteObjectHandler: object lock check failed for %s/%s: %v" , bucket , object , lockErr )
s3err . WriteErrorResponse ( w , r , s3err . ErrAccessDenied )
return
}
// Delete the "null" version (the regular file)
err := s3a . deleteSpecificObjectVersion ( bucket , object , "null" )
// Delete the "null" version (the regular file), passing prefetched entry
err := s3a . deleteSpecificObjectVersion ( bucket , object , "null" , prefetchedEntry )
if err != nil {
glog . Errorf ( "Failed to delete null version: %v" , err )
s3err . WriteErrorResponse ( w , r , s3err . ErrInternalError )
@ -235,10 +239,14 @@ func (s3a *S3ApiServer) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *h
}
// Check object lock permissions before deletion (only for versioned buckets)
// The returned entry is reused to avoid duplicate filer lookups
var prefetchedEntry * filer_pb . Entry
if versioningConfigured {
// Validate governance bypass for this specific object
governanceBypassAllowed := s3a . evaluateGovernanceBypassRequest ( r , bucket , object . Key )
if _ , lockErr := s3a . enforceObjectLockProtections ( r , bucket , object . Key , object . VersionId , governanceBypassAllowed ) ; lockErr != nil {
var lockErr error
prefetchedEntry , lockErr = s3a . enforceObjectLockProtections ( r , bucket , object . Key , object . VersionId , governanceBypassAllowed )
if lockErr != nil {
glog . V ( 2 ) . Infof ( "DeleteMultipleObjectsHandler: object lock check failed for %s/%s (version: %s): %v" , bucket , object . Key , object . VersionId , lockErr )
deleteErrors = append ( deleteErrors , DeleteError {
Code : s3err . GetAPIError ( s3err . ErrAccessDenied ) . Code ,
@ -257,7 +265,8 @@ func (s3a *S3ApiServer) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *h
// Handle versioned delete based on specific versioning state
if object . VersionId != "" {
// Delete specific version (same for both enabled and suspended)
err := s3a . deleteSpecificObjectVersion ( bucket , object . Key , object . VersionId )
// Pass prefetched entry to avoid duplicate lookup
err := s3a . deleteSpecificObjectVersion ( bucket , object . Key , object . VersionId , prefetchedEntry )
if err != nil {
deleteErrors = append ( deleteErrors , DeleteError {
Code : "" ,
@ -288,7 +297,8 @@ func (s3a *S3ApiServer) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *h
// Suspended versioning: Actually delete the "null" version object
glog . V ( 2 ) . Infof ( "DeleteMultipleObjectsHandler: deleting null version for suspended versioning %s/%s" , bucket , object . Key )
err := s3a . deleteSpecificObjectVersion ( bucket , object . Key , "null" )
// Pass prefetched entry to avoid duplicate lookup
err := s3a . deleteSpecificObjectVersion ( bucket , object . Key , "null" , prefetchedEntry )
if err != nil {
deleteErrors = append ( deleteErrors , DeleteError {
Code : "" ,