@@ -76,6 +76,7 @@ type S3Config struct {
76
76
SecretAccessKey flagext.Secret `yaml:"secret_access_key"`
77
77
SessionToken flagext.Secret `yaml:"session_token"`
78
78
Insecure bool `yaml:"insecure"`
79
+ ChunkDelimiter string `yaml:"chunk_delimiter"`
79
80
HTTPConfig HTTPConfig `yaml:"http_config"`
80
81
SignatureVersion string `yaml:"signature_version"`
81
82
StorageClass string `yaml:"storage_class"`
@@ -113,6 +114,7 @@ func (cfg *S3Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
113
114
f .Var (& cfg .SecretAccessKey , prefix + "s3.secret-access-key" , "AWS Secret Access Key" )
114
115
f .Var (& cfg .SessionToken , prefix + "s3.session-token" , "AWS Session Token" )
115
116
f .BoolVar (& cfg .Insecure , prefix + "s3.insecure" , false , "Disable https on s3 connection." )
117
+ f .StringVar (& cfg .ChunkDelimiter , prefix + "s3.chunk-delimiter" , "" , "Delimiter used to replace the default delimiter ':' in chunk IDs when storing chunks. This is mainly intended when you run a MinIO instance on a Windows machine. You should not change this value inflight." )
116
118
f .BoolVar (& cfg .DisableDualstack , prefix + "s3.disable-dualstack" , false , "Disable forcing S3 dualstack endpoint usage." )
117
119
118
120
cfg .SSEConfig .RegisterFlagsWithPrefix (prefix + "s3.sse." , f )
@@ -335,7 +337,7 @@ func (a *S3ObjectClient) objectAttributes(ctx context.Context, objectKey, method
335
337
lastErr = instrument .CollectedRequest (ctx , method , s3RequestDuration , instrument .ErrorCode , func (_ context.Context ) error {
336
338
headObjectInput := & s3.HeadObjectInput {
337
339
Bucket : aws .String (a .bucketFromKey (objectKey )),
338
- Key : aws .String (objectKey ),
340
+ Key : aws .String (a . convertObjectKey ( objectKey , true ) ),
339
341
}
340
342
headOutput , requestErr := a .S3 .HeadObject (headObjectInput )
341
343
if requestErr != nil {
@@ -365,7 +367,7 @@ func (a *S3ObjectClient) DeleteObject(ctx context.Context, objectKey string) err
365
367
return instrument .CollectedRequest (ctx , "S3.DeleteObject" , s3RequestDuration , instrument .ErrorCode , func (ctx context.Context ) error {
366
368
deleteObjectInput := & s3.DeleteObjectInput {
367
369
Bucket : aws .String (a .bucketFromKey (objectKey )),
368
- Key : aws .String (objectKey ),
370
+ Key : aws .String (a . convertObjectKey ( objectKey , true ) ),
369
371
}
370
372
371
373
_ , err := a .S3 .DeleteObjectWithContext (ctx , deleteObjectInput )
@@ -405,7 +407,7 @@ func (a *S3ObjectClient) GetObject(ctx context.Context, objectKey string) (io.Re
405
407
var requestErr error
406
408
resp , requestErr = a .hedgedS3 .GetObjectWithContext (ctx , & s3.GetObjectInput {
407
409
Bucket : aws .String (bucket ),
408
- Key : aws .String (objectKey ),
410
+ Key : aws .String (a . convertObjectKey ( objectKey , true ) ),
409
411
})
410
412
return requestErr
411
413
})
@@ -442,7 +444,7 @@ func (a *S3ObjectClient) GetObjectRange(ctx context.Context, objectKey string, o
442
444
var requestErr error
443
445
resp , requestErr = a .hedgedS3 .GetObjectWithContext (ctx , & s3.GetObjectInput {
444
446
Bucket : aws .String (bucket ),
445
- Key : aws .String (objectKey ),
447
+ Key : aws .String (a . convertObjectKey ( objectKey , true ) ),
446
448
Range : aws .String (fmt .Sprintf ("bytes=%d-%d" , offset , offset + length - 1 )),
447
449
})
448
450
return requestErr
@@ -467,7 +469,7 @@ func (a *S3ObjectClient) PutObject(ctx context.Context, objectKey string, object
467
469
putObjectInput := & s3.PutObjectInput {
468
470
Body : readSeeker ,
469
471
Bucket : aws .String (a .bucketFromKey (objectKey )),
470
- Key : aws .String (objectKey ),
472
+ Key : aws .String (a . convertObjectKey ( objectKey , true ) ),
471
473
StorageClass : aws .String (a .cfg .StorageClass ),
472
474
}
473
475
@@ -504,7 +506,7 @@ func (a *S3ObjectClient) List(ctx context.Context, prefix, delimiter string) ([]
504
506
505
507
for _ , content := range output .Contents {
506
508
storageObjects = append (storageObjects , client.StorageObject {
507
- Key : * content .Key ,
509
+ Key : a . convertObjectKey ( * content .Key , false ) ,
508
510
ModifiedAt : * content .LastModified ,
509
511
})
510
512
}
@@ -617,3 +619,15 @@ func IsRetryableErr(err error) bool {
617
619
func (a * S3ObjectClient ) IsRetryableErr (err error ) bool {
618
620
return IsRetryableErr (err )
619
621
}
622
+
623
+ // convertObjectKey modifies the object key based on a delimiter and a mode flag determining conversion.
624
+ func (a * S3ObjectClient ) convertObjectKey (objectKey string , toS3 bool ) string {
625
+ if len (a .cfg .ChunkDelimiter ) == 1 {
626
+ if toS3 {
627
+ objectKey = strings .ReplaceAll (objectKey , ":" , a .cfg .ChunkDelimiter )
628
+ } else {
629
+ objectKey = strings .ReplaceAll (objectKey , a .cfg .ChunkDelimiter , ":" )
630
+ }
631
+ }
632
+ return objectKey
633
+ }
0 commit comments