Skip to content

Commit

Permalink
feat(storage): multi bucket get url (#5659)
Browse files Browse the repository at this point in the history
  • Loading branch information
Equartey authored and Nika Hassani committed Nov 20, 2024
1 parent e5bb5d4 commit 77a2fd7
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 21 deletions.
12 changes: 10 additions & 2 deletions packages/amplify_core/lib/src/types/storage/get_url_options.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:aws_common/aws_common.dart';
import 'package:amplify_core/amplify_core.dart';

/// {@template amplify_core.storage.get_url_options}
/// Configurable options for `Amplify.Storage.getUrl`.
Expand All @@ -14,20 +14,28 @@ class StorageGetUrlOptions
/// {@macro amplify_core.storage.get_url_options}
const StorageGetUrlOptions({
this.pluginOptions,
this.bucket,
});

/// {@macro amplify_core.storage.get_url_plugin_options}
final StorageGetUrlPluginOptions? pluginOptions;

/// Optionally specify which bucket to target
final StorageBucket? bucket;

@override
List<Object?> get props => [pluginOptions];
List<Object?> get props => [
pluginOptions,
bucket,
];

@override
String get runtimeTypeName => 'StorageGetUrlOptions';

@override
Map<String, Object?> toJson() => {
'pluginOptions': pluginOptions?.toJson(),
'bucket': bucket,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,62 @@ void main() {
expect(actualData, data);
});
});

group('multi bucket', () {
final mainBucket = StorageBucket.fromOutputs(
'Storage Integ Test main bucket',
);
final secondaryBucket = StorageBucket.fromOutputs(
'Storage Integ Test secondary bucket',
);
final pathMain = 'public/multi-bucket-get-url-${uuid()}';
final pathSecondary = 'public/multi-bucket-get-url-${uuid()}';
final storagePathMain = StoragePath.fromString(pathMain);
final storagePathSecondary = StoragePath.fromString(pathSecondary);

setUp(() async {
addTearDownPath(storagePathMain);
addTearDownPath(storagePathSecondary);
await Amplify.Storage.uploadData(
data: StorageDataPayload.bytes(data),
path: storagePathMain,
options: StorageUploadDataOptions(
bucket: mainBucket,
),
).result;
await Amplify.Storage.uploadData(
data: StorageDataPayload.bytes(data),
path: storagePathSecondary,
options: StorageUploadDataOptions(
bucket: secondaryBucket,
),
).result;
});

testWidgets('can get url from main bucket', (_) async {
final result = await Amplify.Storage.getUrl(
path: storagePathMain,
options: StorageGetUrlOptions(
bucket: mainBucket,
),
).result;
expect(result.url.path, '/$pathMain');
final actualData = await readData(result.url);
expect(actualData, data);
});

testWidgets('can get url from secondary bucket', (_) async {
final result = await Amplify.Storage.getUrl(
path: storagePathSecondary,
options: StorageGetUrlOptions(
bucket: secondaryBucket,
),
).result;
expect(result.url.path, '/$pathSecondary');
final actualData = await readData(result.url);
expect(actualData, data);
});
});
});

group('config with dots in name', () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ class AmplifyStorageS3Dart extends StoragePluginInterface

final s3Options = StorageGetUrlOptions(
pluginOptions: s3PluginOptions,
bucket: options?.bucket,
);

return S3GetUrlOperation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,10 @@ class StorageS3Service {
}) async {
final s3PluginOptions = options.pluginOptions as S3GetUrlPluginOptions? ??
const S3GetUrlPluginOptions();
final s3ClientInfo = getS3ClientInfo(storageBucket: options.bucket);

if (s3PluginOptions.useAccelerateEndpoint &&
_defaultS3ClientConfig.usePathStyle) {
s3ClientInfo.config.usePathStyle) {
throw s3_exception.accelerateEndpointUnusable;
}

Expand All @@ -234,20 +235,20 @@ class StorageS3Service {
// the `getProperties` API (i.e. HeadObject)
await getProperties(
path: path,
options: const StorageGetPropertiesOptions(),
options: StorageGetPropertiesOptions(bucket: options.bucket),
);
}

var resolvedPath = await _pathResolver.resolvePath(path: path);
var host =
'${_storageOutputs.bucketName}.${_getS3EndpointHost(region: _storageOutputs.awsRegion)}';
if (_defaultS3ClientConfig.usePathStyle) {
host = host.replaceFirst('${_storageOutputs.bucketName}.', '');
resolvedPath = '${_storageOutputs.bucketName}/$resolvedPath';
'${s3ClientInfo.bucketName}.${_getS3EndpointHost(region: s3ClientInfo.awsRegion)}';
if (s3ClientInfo.config.usePathStyle) {
host = host.replaceFirst('${s3ClientInfo.bucketName}.', '');
resolvedPath = '${s3ClientInfo.bucketName}/$resolvedPath';
} else if (s3PluginOptions.useAccelerateEndpoint) {
// https: //docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration-getting-started.html
host = host
.replaceFirst(RegExp('${_storageOutputs.awsRegion}\\.'), '')
.replaceFirst(RegExp('${s3ClientInfo.awsRegion}\\.'), '')
.replaceFirst(RegExp(r'\.s3\.'), '.s3-accelerate.');
}

Expand All @@ -263,7 +264,7 @@ class StorageS3Service {
credentialsProvider: _credentialsProvider,
);
final signerScope = sigv4.AWSCredentialScope(
region: _storageOutputs.awsRegion,
region: s3ClientInfo.awsRegion,
service: AWSService.s3,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ void main() {
expiresIn: Duration(minutes: 10),
useAccelerateEndpoint: true,
),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);

when(
Expand Down Expand Up @@ -418,9 +421,6 @@ void main() {
() async {
const defaultOptions = StorageDownloadDataOptions(
pluginOptions: S3DownloadDataPluginOptions(),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);

when(
Expand All @@ -438,7 +438,6 @@ void main() {

downloadDataOperation = storageS3Plugin.downloadData(
path: const StoragePath.fromString('public/$testKey'),
options: defaultOptions,
);

final capturedOptions = verify(
Expand Down Expand Up @@ -471,6 +470,9 @@ void main() {
useAccelerateEndpoint: true,
getProperties: true,
),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);

when(
Expand Down Expand Up @@ -737,9 +739,6 @@ void main() {
() async {
const defaultOptions = StorageUploadFileOptions(
pluginOptions: S3UploadFilePluginOptions(),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);

when(
Expand All @@ -758,7 +757,6 @@ void main() {
uploadFileOperation = storageS3Plugin.uploadFile(
path: testPath,
localFile: testLocalFile,
options: defaultOptions,
);

final capturedParams = verify(
Expand Down Expand Up @@ -798,6 +796,9 @@ void main() {
getProperties: true,
useAccelerateEndpoint: true,
),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);

when(
Expand Down Expand Up @@ -984,9 +985,6 @@ void main() {
() async {
const defaultOptions = StorageRemoveOptions(
pluginOptions: S3RemovePluginOptions(),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);
when(
() => storageS3Service.remove(
Expand Down Expand Up @@ -1024,6 +1022,9 @@ void main() {
test('should forward options to StorageS3Service.remove() API', () async {
const testOptions = StorageRemoveOptions(
pluginOptions: S3RemovePluginOptions(),
bucket: StorageBucket.fromBucketInfo(
BucketInfo(bucketName: 'unit-test-bucket', region: 'us-east-2'),
),
);

when(
Expand Down

0 comments on commit 77a2fd7

Please sign in to comment.