Skip to content

Commit b432822

Browse files
authoredNov 24, 2021
feat(s3): support Transfer Acceleration (#17636)
Add support for S3 [Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration.html). This PR introduces: - New boolean property `transferAcceleration` to enable Transfer Acceleration. - New operation `transferAccelerationUrlForObject()` to get HTTPS endpoint for Transfer Acceleration. Closes #12570. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 6c7550b commit b432822

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed
 

‎packages/@aws-cdk/aws-s3/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,22 @@ const bucket = new s3.Bucket(this, 'MyTempFileBucket', {
463463
switching this to `false` in a CDK version *before* `1.126.0` will lead to
464464
all objects in the bucket being deleted. Be sure to update your bucket resources
465465
by deploying with CDK version `1.126.0` or later **before** switching this value to `false`.
466+
467+
## Transfer Acceleration
468+
469+
[Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration.html) can be configured to enable fast, easy, and secure transfers of files over long distances:
470+
471+
```ts
472+
const bucket = new s3.Bucket(this, 'MyBucket', {
473+
transferAcceleration: true,
474+
});
475+
```
476+
477+
To access the bucket that is enabled for Transfer Acceleration, you must use a special endpoint. The URL can be generated using method `transferAccelerationUrlForObject`:
478+
479+
```ts
480+
const bucket = new s3.Bucket(this, 'MyBucket', {
481+
transferAcceleration: true,
482+
});
483+
bucket.transferAccelerationUrlForObject('objectname');
484+
```

‎packages/@aws-cdk/aws-s3/lib/bucket.ts

+55
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,20 @@ export interface IBucket extends IResource {
115115
*/
116116
urlForObject(key?: string): string;
117117

118+
/**
119+
* The https Transfer Acceleration URL of an S3 object. Specify `dualStack: true` at the options
120+
* for dual-stack endpoint (connect to the bucket over IPv6). For example:
121+
*
122+
* - `https://bucket.s3-accelerate.amazonaws.com`
123+
* - `https://bucket.s3-accelerate.amazonaws.com/key`
124+
*
125+
* @param key The S3 key of the object. If not specified, the URL of the
126+
* bucket is returned.
127+
* @param options Options for generating URL.
128+
* @returns an TransferAccelerationUrl token
129+
*/
130+
transferAccelerationUrlForObject(key?: string, options?: TransferAccelerationUrlOptions): string;
131+
118132
/**
119133
* The virtual hosted-style URL of an S3 object. Specify `regional: false` at
120134
* the options for non-regional URL. For example:
@@ -623,6 +637,27 @@ export abstract class BucketBase extends Resource implements IBucket {
623637
return this.urlJoin(prefix, this.bucketName, key);
624638
}
625639

640+
/**
641+
* The https Transfer Acceleration URL of an S3 object. Specify `dualStack: true` at the options
642+
* for dual-stack endpoint (connect to the bucket over IPv6). For example:
643+
*
644+
* - `https://bucket.s3-accelerate.amazonaws.com`
645+
* - `https://bucket.s3-accelerate.amazonaws.com/key`
646+
*
647+
* @param key The S3 key of the object. If not specified, the URL of the
648+
* bucket is returned.
649+
* @param options Options for generating URL.
650+
* @returns an TransferAccelerationUrl token
651+
*/
652+
public transferAccelerationUrlForObject(key?: string, options?: TransferAccelerationUrlOptions): string {
653+
const dualStack = options?.dualStack ? '.dualstack' : '';
654+
const prefix = `https://${this.bucketName}.s3-accelerate${dualStack}.amazonaws.com/`;
655+
if (typeof key !== 'string') {
656+
return this.urlJoin(prefix);
657+
}
658+
return this.urlJoin(prefix, key);
659+
}
660+
626661
/**
627662
* The virtual hosted-style URL of an S3 object. Specify `regional: false` at
628663
* the options for non-regional URL. For example:
@@ -1369,6 +1404,13 @@ export interface BucketProps {
13691404
*
13701405
*/
13711406
readonly objectOwnership?: ObjectOwnership;
1407+
1408+
/**
1409+
* Whether this bucket should have transfer acceleration turned on or not.
1410+
*
1411+
* @default false
1412+
*/
1413+
readonly transferAcceleration?: boolean;
13721414
}
13731415

13741416
/**
@@ -1535,6 +1577,7 @@ export class Bucket extends BucketBase {
15351577
loggingConfiguration: this.parseServerAccessLogs(props),
15361578
inventoryConfigurations: Lazy.any({ produce: () => this.parseInventoryConfiguration() }),
15371579
ownershipControls: this.parseOwnershipControls(props),
1580+
accelerateConfiguration: props.transferAcceleration ? { accelerationStatus: 'Enabled' } : undefined,
15381581
});
15391582
this._resource = resource;
15401583

@@ -2330,6 +2373,18 @@ export interface VirtualHostedStyleUrlOptions {
23302373
readonly regional?: boolean;
23312374
}
23322375

2376+
/**
2377+
* Options for creating a Transfer Acceleration URL.
2378+
*/
2379+
export interface TransferAccelerationUrlOptions {
2380+
/**
2381+
* Dual-stack support to connect to the bucket over IPv6.
2382+
*
2383+
* @default - false
2384+
*/
2385+
readonly dualStack?: boolean;
2386+
}
2387+
23332388
function mapOrUndefined<T, U>(list: T[] | undefined, callback: (element: T) => U): U[] | undefined {
23342389
if (!list || list.length === 0) {
23352390
return undefined;

‎packages/@aws-cdk/aws-s3/test/bucket.test.ts

+169
Original file line numberDiff line numberDiff line change
@@ -2479,4 +2479,173 @@ describe('bucket', () => {
24792479
autoDeleteObjects: true,
24802480
})).toThrow(/Cannot use \'autoDeleteObjects\' property on a bucket without setting removal policy to \'DESTROY\'/);
24812481
});
2482+
2483+
test('bucket with transfer acceleration turned on', () => {
2484+
const stack = new cdk.Stack();
2485+
new s3.Bucket(stack, 'MyBucket', {
2486+
transferAcceleration: true,
2487+
});
2488+
2489+
expect(stack).toMatchTemplate({
2490+
'Resources': {
2491+
'MyBucketF68F3FF0': {
2492+
'Type': 'AWS::S3::Bucket',
2493+
'Properties': {
2494+
'AccelerateConfiguration': {
2495+
'AccelerationStatus': 'Enabled',
2496+
},
2497+
},
2498+
'DeletionPolicy': 'Retain',
2499+
'UpdateReplacePolicy': 'Retain',
2500+
},
2501+
},
2502+
});
2503+
2504+
});
2505+
2506+
test('transferAccelerationUrlForObject returns a token with the S3 URL of the token', () => {
2507+
const stack = new cdk.Stack();
2508+
const bucket = new s3.Bucket(stack, 'MyBucket');
2509+
const bucketWithRegion = s3.Bucket.fromBucketAttributes(stack, 'RegionalBucket', {
2510+
bucketArn: 'arn:aws:s3:::explicit-region-bucket',
2511+
region: 'us-west-2',
2512+
});
2513+
2514+
new cdk.CfnOutput(stack, 'BucketURL', { value: bucket.transferAccelerationUrlForObject() });
2515+
new cdk.CfnOutput(stack, 'MyFileURL', { value: bucket.transferAccelerationUrlForObject('my/file.txt') });
2516+
new cdk.CfnOutput(stack, 'YourFileURL', { value: bucket.transferAccelerationUrlForObject('/your/file.txt') }); // "/" is optional
2517+
new cdk.CfnOutput(stack, 'RegionBucketURL', { value: bucketWithRegion.transferAccelerationUrlForObject() });
2518+
2519+
expect(stack).toMatchTemplate({
2520+
'Resources': {
2521+
'MyBucketF68F3FF0': {
2522+
'Type': 'AWS::S3::Bucket',
2523+
'DeletionPolicy': 'Retain',
2524+
'UpdateReplacePolicy': 'Retain',
2525+
},
2526+
},
2527+
'Outputs': {
2528+
'BucketURL': {
2529+
'Value': {
2530+
'Fn::Join': [
2531+
'',
2532+
[
2533+
'https://',
2534+
{
2535+
'Ref': 'MyBucketF68F3FF0',
2536+
},
2537+
'.s3-accelerate.amazonaws.com/',
2538+
],
2539+
],
2540+
},
2541+
},
2542+
'MyFileURL': {
2543+
'Value': {
2544+
'Fn::Join': [
2545+
'',
2546+
[
2547+
'https://',
2548+
{
2549+
'Ref': 'MyBucketF68F3FF0',
2550+
},
2551+
'.s3-accelerate.amazonaws.com/my/file.txt',
2552+
],
2553+
],
2554+
},
2555+
},
2556+
'YourFileURL': {
2557+
'Value': {
2558+
'Fn::Join': [
2559+
'',
2560+
[
2561+
'https://',
2562+
{
2563+
'Ref': 'MyBucketF68F3FF0',
2564+
},
2565+
'.s3-accelerate.amazonaws.com/your/file.txt',
2566+
],
2567+
],
2568+
},
2569+
},
2570+
'RegionBucketURL': {
2571+
'Value': 'https://explicit-region-bucket.s3-accelerate.amazonaws.com/',
2572+
},
2573+
},
2574+
});
2575+
2576+
2577+
});
2578+
2579+
test('transferAccelerationUrlForObject with dual stack option returns a token with the S3 URL of the token', () => {
2580+
const stack = new cdk.Stack();
2581+
const bucket = new s3.Bucket(stack, 'MyBucket');
2582+
const bucketWithRegion = s3.Bucket.fromBucketAttributes(stack, 'RegionalBucket', {
2583+
bucketArn: 'arn:aws:s3:::explicit-region-bucket',
2584+
region: 'us-west-2',
2585+
});
2586+
2587+
new cdk.CfnOutput(stack, 'BucketURL', { value: bucket.transferAccelerationUrlForObject(undefined, { dualStack: true }) });
2588+
new cdk.CfnOutput(stack, 'MyFileURL', { value: bucket.transferAccelerationUrlForObject('my/file.txt', { dualStack: true }) });
2589+
new cdk.CfnOutput(stack, 'YourFileURL', { value: bucket.transferAccelerationUrlForObject('/your/file.txt', { dualStack: true }) }); // "/" is optional
2590+
new cdk.CfnOutput(stack, 'RegionBucketURL', { value: bucketWithRegion.transferAccelerationUrlForObject(undefined, { dualStack: true }) });
2591+
2592+
expect(stack).toMatchTemplate({
2593+
'Resources': {
2594+
'MyBucketF68F3FF0': {
2595+
'Type': 'AWS::S3::Bucket',
2596+
'DeletionPolicy': 'Retain',
2597+
'UpdateReplacePolicy': 'Retain',
2598+
},
2599+
},
2600+
'Outputs': {
2601+
'BucketURL': {
2602+
'Value': {
2603+
'Fn::Join': [
2604+
'',
2605+
[
2606+
'https://',
2607+
{
2608+
'Ref': 'MyBucketF68F3FF0',
2609+
},
2610+
'.s3-accelerate.dualstack.amazonaws.com/',
2611+
],
2612+
],
2613+
},
2614+
},
2615+
'MyFileURL': {
2616+
'Value': {
2617+
'Fn::Join': [
2618+
'',
2619+
[
2620+
'https://',
2621+
{
2622+
'Ref': 'MyBucketF68F3FF0',
2623+
},
2624+
'.s3-accelerate.dualstack.amazonaws.com/my/file.txt',
2625+
],
2626+
],
2627+
},
2628+
},
2629+
'YourFileURL': {
2630+
'Value': {
2631+
'Fn::Join': [
2632+
'',
2633+
[
2634+
'https://',
2635+
{
2636+
'Ref': 'MyBucketF68F3FF0',
2637+
},
2638+
'.s3-accelerate.dualstack.amazonaws.com/your/file.txt',
2639+
],
2640+
],
2641+
},
2642+
},
2643+
'RegionBucketURL': {
2644+
'Value': 'https://explicit-region-bucket.s3-accelerate.dualstack.amazonaws.com/',
2645+
},
2646+
},
2647+
});
2648+
2649+
2650+
});
24822651
});

0 commit comments

Comments
 (0)
Please sign in to comment.