aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/minio-go/v7/api-remove.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/minio/minio-go/v7/api-remove.go')
-rw-r--r--vendor/github.com/minio/minio-go/v7/api-remove.go70
1 files changed, 70 insertions, 0 deletions
diff --git a/vendor/github.com/minio/minio-go/v7/api-remove.go b/vendor/github.com/minio/minio-go/v7/api-remove.go
index 6c2ab78020..920612c4fe 100644
--- a/vendor/github.com/minio/minio-go/v7/api-remove.go
+++ b/vendor/github.com/minio/minio-go/v7/api-remove.go
@@ -24,6 +24,7 @@ import (
"io"
"net/http"
"net/url"
+ "time"
"github.com/minio/minio-go/v7/pkg/s3utils"
)
@@ -58,10 +59,18 @@ func (c Client) RemoveBucket(ctx context.Context, bucketName string) error {
return nil
}
+// AdvancedRemoveOptions intended for internal use by replication
+type AdvancedRemoveOptions struct {
+ ReplicationDeleteMarker bool
+ ReplicationStatus ReplicationStatus
+ ReplicationMTime time.Time
+}
+
// RemoveObjectOptions represents options specified by user for RemoveObject call
type RemoveObjectOptions struct {
GovernanceBypass bool
VersionID string
+ Internal AdvancedRemoveOptions
}
// RemoveObject removes an object from a bucket.
@@ -74,6 +83,11 @@ func (c Client) RemoveObject(ctx context.Context, bucketName, objectName string,
return err
}
+ return c.removeObject(ctx, bucketName, objectName, opts)
+}
+
+func (c Client) removeObject(ctx context.Context, bucketName, objectName string, opts RemoveObjectOptions) error {
+
// Get resources properly escaped and lined up before
// using them in http request.
urlValues := make(url.Values)
@@ -89,6 +103,15 @@ func (c Client) RemoveObject(ctx context.Context, bucketName, objectName string,
// Set the bypass goverenance retention header
headers.Set(amzBypassGovernance, "true")
}
+ if opts.Internal.ReplicationDeleteMarker {
+ headers.Set(minIOBucketReplicationDeleteMarker, "true")
+ }
+ if !opts.Internal.ReplicationMTime.IsZero() {
+ headers.Set(minIOBucketSourceMTime, opts.Internal.ReplicationMTime.Format(time.RFC3339))
+ }
+ if !opts.Internal.ReplicationStatus.Empty() {
+ headers.Set(amzBucketReplicationStatus, string(opts.Internal.ReplicationStatus))
+ }
// Execute DELETE on objectName.
resp, err := c.executeMethod(ctx, http.MethodDelete, requestMetadata{
bucketName: bucketName,
@@ -147,8 +170,14 @@ func processRemoveMultiObjectsResponse(body io.Reader, objects []ObjectInfo, err
// Fill deletion that returned an error.
for _, obj := range rmResult.UnDeletedObjects {
+ // Version does not exist is not an error ignore and continue.
+ switch obj.Code {
+ case "InvalidArgument", "NoSuchVersion":
+ continue
+ }
errorCh <- RemoveObjectError{
ObjectName: obj.Key,
+ VersionID: obj.VersionID,
Err: ErrorResponse{
Code: obj.Code,
Message: obj.Message,
@@ -189,6 +218,26 @@ func (c Client) RemoveObjects(ctx context.Context, bucketName string, objectsCh
return errorCh
}
+// Return true if the character is within the allowed characters in an XML 1.0 document
+// The list of allowed characters can be found here: https://www.w3.org/TR/xml/#charsets
+func validXMLChar(r rune) (ok bool) {
+ return r == 0x09 ||
+ r == 0x0A ||
+ r == 0x0D ||
+ r >= 0x20 && r <= 0xD7FF ||
+ r >= 0xE000 && r <= 0xFFFD ||
+ r >= 0x10000 && r <= 0x10FFFF
+}
+
+func hasInvalidXMLChar(str string) bool {
+ for _, s := range str {
+ if !validXMLChar(s) {
+ return true
+ }
+ }
+ return false
+}
+
// Generate and call MultiDelete S3 requests based on entries received from objectsCh
func (c Client) removeObjects(ctx context.Context, bucketName string, objectsCh <-chan ObjectInfo, errorCh chan<- RemoveObjectError, opts RemoveObjectsOptions) {
maxEntries := 1000
@@ -209,6 +258,27 @@ func (c Client) removeObjects(ctx context.Context, bucketName string, objectsCh
// Try to gather 1000 entries
for object := range objectsCh {
+ if hasInvalidXMLChar(object.Key) {
+ // Use single DELETE so the object name will be in the request URL instead of the multi-delete XML document.
+ err := c.removeObject(ctx, bucketName, object.Key, RemoveObjectOptions{
+ VersionID: object.VersionID,
+ GovernanceBypass: opts.GovernanceBypass,
+ })
+ if err != nil {
+ // Version does not exist is not an error ignore and continue.
+ switch ToErrorResponse(err).Code {
+ case "InvalidArgument", "NoSuchVersion":
+ continue
+ }
+ errorCh <- RemoveObjectError{
+ ObjectName: object.Key,
+ VersionID: object.VersionID,
+ Err: err,
+ }
+ }
+ continue
+ }
+
batch = append(batch, object)
if count++; count >= maxEntries {
break