diff --git a/command/app.go b/command/app.go index f1699e43d..6fa949363 100644 --- a/command/app.go +++ b/command/app.go @@ -90,6 +90,15 @@ var app = &cli.App{ Name: "credentials-file", Usage: "use the specified credentials file instead of the default credentials file", }, + &cli.GenericFlag{ + Name: "addressing-style", + Usage: "use virtual host style or path style endpoint: (path, virtual)", + Value: &EnumValue{ + Enum: []string{"path", "virtual"}, + Default: "path", + }, + EnvVars: []string{"S3_ADDRESSING_STYLE"}, + }, }, Before: func(c *cli.Context) error { retryCount := c.Int("retry-count") @@ -190,6 +199,7 @@ func NewStorageOpts(c *cli.Context) storage.Options { CredentialFile: c.String("credentials-file"), LogLevel: log.LevelFromString(c.String("log")), NoSuchUploadRetryCount: c.Int("no-such-upload-retry-count"), + AddressingStyle: c.String("addressing-style"), } } diff --git a/main.go b/main.go index 3d835cbcb..495a3e5fe 100644 --- a/main.go +++ b/main.go @@ -12,7 +12,6 @@ import ( func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() - if err := command.Main(ctx, os.Args); err != nil { os.Exit(1) } diff --git a/storage/s3.go b/storage/s3.go index 3313be66e..b078f93d5 100644 --- a/storage/s3.go +++ b/storage/s3.go @@ -50,6 +50,8 @@ const ( // the key of the object metadata which is used to handle retry decision on NoSuchUpload error metadataKeyRetryID = "s5cmd-upload-retry-id" + + AddressingVirtualHostStyle = "virtual" ) // Re-used AWS sessions dramatically improve performance. @@ -1255,7 +1257,7 @@ func (sc *SessionCache) newSession(ctx context.Context, opts Options) (*session. // use virtual-host-style if the endpoint is known to support it, // otherwise use the path-style approach. - isVirtualHostStyle := isVirtualHostStyle(endpointURL) + isVirtualHostStyle := isVirtualHostStyle(endpointURL, opts.AddressingStyle) useAccelerate := supportsTransferAcceleration(endpointURL) // AWS SDK handles transfer acceleration automatically. Setting the @@ -1422,11 +1424,18 @@ func IsGoogleEndpoint(endpoint urlpkg.URL) bool { return endpoint.Hostname() == gcsEndpoint } +func ForcedVirtualHostStyle(endpoint urlpkg.URL, addressingStyle string) bool { + return addressingStyle == AddressingVirtualHostStyle +} + // isVirtualHostStyle reports whether the given endpoint supports S3 virtual // host style bucket name resolving. If a custom S3 API compatible endpoint is // given, resolve the bucketname from the URL path. -func isVirtualHostStyle(endpoint urlpkg.URL) bool { - return endpoint == sentinelURL || supportsTransferAcceleration(endpoint) || IsGoogleEndpoint(endpoint) +func isVirtualHostStyle(endpoint urlpkg.URL, addressingStyle string) bool { + return endpoint == sentinelURL || + supportsTransferAcceleration(endpoint) || + IsGoogleEndpoint(endpoint) || + ForcedVirtualHostStyle(endpoint, addressingStyle) } func errHasCode(err error, code string) bool { diff --git a/storage/storage.go b/storage/storage.go index 1a6171263..4dbc38113 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -71,6 +71,7 @@ func NewRemoteClient(ctx context.Context, url *url.URL, opts Options) (*S3, erro LogLevel: opts.LogLevel, bucket: url.Bucket, region: opts.region, + AddressingStyle: opts.AddressingStyle, } return newS3Storage(ctx, newOpts) } @@ -97,6 +98,7 @@ type Options struct { CredentialFile string bucket string region string + AddressingStyle string } func (o *Options) SetRegion(region string) {