From 34f453d59aea17d0153ec84d61dc916c82c8b0fe Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Thu, 21 Oct 2021 23:36:28 +0530 Subject: [PATCH 1/5] feat(amplify): Add support for custom headers in the App --- package.json | 2 + packages/@aws-cdk/aws-amplify/README.md | 29 ++++++++++++ packages/@aws-cdk/aws-amplify/lib/app.ts | 47 +++++++++++++++++++ packages/@aws-cdk/aws-amplify/package.json | 9 +++- .../@aws-cdk/aws-amplify/test/app.test.ts | 31 ++++++++++++ .../aws-amplify/test/integ.app.expected.json | 1 + .../@aws-cdk/aws-amplify/test/integ.app.ts | 15 ++++++ 7 files changed, 132 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7db1f7c20c0ad..5d51d46076aba 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,8 @@ "@aws-cdk/assertions/string-width/**", "@aws-cdk/assertions/table", "@aws-cdk/assertions/table/**", + "@aws-cdk/aws-amplify/yaml", + "@aws-cdk/aws-amplify/yaml/**", "@aws-cdk/aws-codebuild/yaml", "@aws-cdk/aws-codebuild/yaml/**", "@aws-cdk/aws-codepipeline-actions/case", diff --git a/packages/@aws-cdk/aws-amplify/README.md b/packages/@aws-cdk/aws-amplify/README.md index a706cb73bb39b..ff2a7a93ae7e2 100644 --- a/packages/@aws-cdk/aws-amplify/README.md +++ b/packages/@aws-cdk/aws-amplify/README.md @@ -178,3 +178,32 @@ const amplifyApp = new amplify.App(this, 'MyApp', { autoBranchDeletion: true, // Automatically disconnect a branch when you delete a branch from your repository }); ``` + +## Adding custom headers + +Use the `customHeaders` prop to configure custom headers for an Amplify app: + +```ts +const amplifyApp = new amplify.App(stack, 'App', { + sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ + owner: '', + repository: '', + oauthToken: cdk.SecretValue.secretsManager('my-github-token') + }), + customHeaders: [ + { + pattern: '*.json', + headers: [ + { key: 'custom-header-name-1', value: 'custom-header-value-1' }, + { key: 'custom-header-name-2', value: 'custom-header-value-2' }, + ], + }, + { + pattern: '/path/*', + headers: [ + { key: 'custom-header-name-1', value: 'custom-header-value-2' }, + ], + }, + ], +}); +``` diff --git a/packages/@aws-cdk/aws-amplify/lib/app.ts b/packages/@aws-cdk/aws-amplify/lib/app.ts index 831921f89dbf8..1e174f09153a5 100644 --- a/packages/@aws-cdk/aws-amplify/lib/app.ts +++ b/packages/@aws-cdk/aws-amplify/lib/app.ts @@ -2,6 +2,7 @@ import * as codebuild from '@aws-cdk/aws-codebuild'; import * as iam from '@aws-cdk/aws-iam'; import { IResource, Lazy, Resource, SecretValue } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import * as YAML from 'yaml'; import { CfnApp } from './amplify.generated'; import { BasicAuth } from './basic-auth'; import { Branch, BranchOptions } from './branch'; @@ -118,6 +119,16 @@ export interface AppProps { */ readonly buildSpec?: codebuild.BuildSpec; + + /** + * The custom HTTP headers for an Amplify app. + * + * @see https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html + * + * @default - no custom headers + */ + readonly customHeaders?: CustomHeader[]; + /** * Custom rewrite/redirect rules for the application * @@ -238,6 +249,7 @@ export class App extends Resource implements IApp, iam.IGrantable { name: props.appName || this.node.id, oauthToken: sourceCodeProviderOptions?.oauthToken?.toString(), repository: sourceCodeProviderOptions?.repository, + customHeaders: props.customHeaders ? renderCustomHeaders(props.customHeaders) : undefined, }); this.appId = app.attrAppId; @@ -486,3 +498,38 @@ export class CustomRule { this.condition = options.condition; } } + +/** + * Custom header of an Amplify App. + */ +export interface CustomHeader { + /** + * The pattern used to match files to be applied with this header. + */ + readonly pattern: string; + + /** + * The array of custom header options to be applied. + */ + readonly headers: CustomHeaderOptions[]; +} + +/** + * Options for any custom header for an Amplify App. + */ +export interface CustomHeaderOptions { + /** + * The name of the custom header. + */ + readonly key: string; + + /** + * The value of the custom header. + */ + readonly value: string; +} + +function renderCustomHeaders(customHeaders: CustomHeader[]): string { + const customHeadersObject = { customHeaders }; + return YAML.stringify(customHeadersObject); +} diff --git a/packages/@aws-cdk/aws-amplify/package.json b/packages/@aws-cdk/aws-amplify/package.json index 13bbcc0ec61d4..7ee41fd004517 100644 --- a/packages/@aws-cdk/aws-amplify/package.json +++ b/packages/@aws-cdk/aws-amplify/package.json @@ -79,7 +79,8 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^26.0.24" + "@types/jest": "^26.0.24", + "@types/yaml": "1.9.6" }, "dependencies": { "@aws-cdk/aws-codebuild": "0.0.0", @@ -88,8 +89,12 @@ "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-secretsmanager": "0.0.0", "@aws-cdk/core": "0.0.0", - "constructs": "^3.3.69" + "constructs": "^3.3.69", + "yaml": "1.10.2" }, + "bundledDependencies": [ + "yaml" + ], "peerDependencies": { "@aws-cdk/aws-codebuild": "0.0.0", "@aws-cdk/aws-codecommit": "0.0.0", diff --git a/packages/@aws-cdk/aws-amplify/test/app.test.ts b/packages/@aws-cdk/aws-amplify/test/app.test.ts index 76b6830bec1c5..2ae1ca5c16ebc 100644 --- a/packages/@aws-cdk/aws-amplify/test/app.test.ts +++ b/packages/@aws-cdk/aws-amplify/test/app.test.ts @@ -394,3 +394,34 @@ test('with auto branch deletion', () => { EnableBranchAutoDeletion: true, }); }); + +test('with custom headers', () => { + // WHEN + new amplify.App(stack, 'App', { + sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ + owner: 'aws', + repository: 'aws-cdk', + oauthToken: SecretValue.plainText('secret'), + }), + customHeaders: [ + { + pattern: '*.json', + headers: [ + { key: 'custom-header-name-1', value: 'custom-header-value-1' }, + { key: 'custom-header-name-2', value: 'custom-header-value-2' }, + ], + }, + { + pattern: '/path/*', + headers: [ + { key: 'custom-header-name-1', value: 'custom-header-value-2' }, + ], + }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { + CustomHeaders: 'customHeaders:\n - pattern: "*.json"\n headers:\n - key: custom-header-name-1\n value: custom-header-value-1\n - key: custom-header-name-2\n value: custom-header-value-2\n - pattern: /path/*\n headers:\n - key: custom-header-name-1\n value: custom-header-value-2\n', + }); +}); diff --git a/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json b/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json index 25971c2ea44a7..d7ddd233378e1 100644 --- a/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json +++ b/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json @@ -54,6 +54,7 @@ }, "Username": "aws" }, + "CustomHeaders": "customHeaders:\n - pattern: \"*.json\"\n headers:\n - key: custom-header-name-1\n value: custom-header-value-1\n - key: custom-header-name-2\n value: custom-header-value-2\n - pattern: /path/*\n headers:\n - key: custom-header-name-1\n value: custom-header-value-2\n", "CustomRules": [ { "Source": "/source", diff --git a/packages/@aws-cdk/aws-amplify/test/integ.app.ts b/packages/@aws-cdk/aws-amplify/test/integ.app.ts index 83ff527a292e2..68fefd0fd3e77 100644 --- a/packages/@aws-cdk/aws-amplify/test/integ.app.ts +++ b/packages/@aws-cdk/aws-amplify/test/integ.app.ts @@ -9,6 +9,21 @@ class TestStack extends Stack { const amplifyApp = new amplify.App(this, 'App', { basicAuth: amplify.BasicAuth.fromGeneratedPassword('aws'), autoBranchCreation: {}, + customHeaders: [ + { + pattern: '*.json', + headers: [ + { key: 'custom-header-name-1', value: 'custom-header-value-1' }, + { key: 'custom-header-name-2', value: 'custom-header-value-2' }, + ], + }, + { + pattern: '/path/*', + headers: [ + { key: 'custom-header-name-1', value: 'custom-header-value-2' }, + ], + }, + ], }); amplifyApp.addCustomRule({ From 100987dba3f4759d64edaac907f5c8ef8b39eba0 Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Fri, 22 Oct 2021 00:04:26 +0530 Subject: [PATCH 2/5] add yaml attribution to NOTICE --- packages/@aws-cdk/aws-amplify/NOTICE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/@aws-cdk/aws-amplify/NOTICE b/packages/@aws-cdk/aws-amplify/NOTICE index 5fc3826926b5b..c84ff36099c3b 100644 --- a/packages/@aws-cdk/aws-amplify/NOTICE +++ b/packages/@aws-cdk/aws-amplify/NOTICE @@ -1,2 +1,23 @@ AWS Cloud Development Kit (AWS CDK) Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +------------------------------------------------------------------------------- + +The AWS CDK includes the following third-party software/licensing: + +** yaml - https://www.npmjs.com/package/yaml +Copyright 2018 Eemeli Aro + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +---------------- From e54f3cf41fc1e490058bc4a11302f026518e7429 Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Sat, 23 Oct 2021 07:37:02 +0530 Subject: [PATCH 3/5] add nohoist for alpha --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 5d51d46076aba..dc5c550e82446 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,8 @@ "@aws-cdk/assertions/table/**", "@aws-cdk/aws-amplify/yaml", "@aws-cdk/aws-amplify/yaml/**", + "@aws-cdk/aws-amplify-alpha/yaml", + "@aws-cdk/aws-amplify/yaml-alpha/**", "@aws-cdk/aws-codebuild/yaml", "@aws-cdk/aws-codebuild/yaml/**", "@aws-cdk/aws-codepipeline-actions/case", From 55ff3740735e53a53cb566b83970f3c108f7011f Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Sat, 23 Oct 2021 08:27:37 +0530 Subject: [PATCH 4/5] fix typo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc5c550e82446..15ed502af725a 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "@aws-cdk/aws-amplify/yaml", "@aws-cdk/aws-amplify/yaml/**", "@aws-cdk/aws-amplify-alpha/yaml", - "@aws-cdk/aws-amplify/yaml-alpha/**", + "@aws-cdk/aws-amplify-alpha/yaml/**", "@aws-cdk/aws-codebuild/yaml", "@aws-cdk/aws-codebuild/yaml/**", "@aws-cdk/aws-codepipeline-actions/case", From 2063e2a97bc9263d1d881eab533c37169ebe2df9 Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Mon, 25 Oct 2021 23:53:18 +0530 Subject: [PATCH 5/5] address comments --- package.json | 4 +- packages/@aws-cdk/aws-amplify/README.md | 20 +++++----- packages/@aws-cdk/aws-amplify/lib/app.ts | 40 +++++++------------ .../@aws-cdk/aws-amplify/test/app.test.ts | 16 ++++---- .../@aws-cdk/aws-amplify/test/integ.app.ts | 16 ++++---- 5 files changed, 43 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 15ed502af725a..6115ddc36950c 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,8 @@ "@aws-cdk/assertions-alpha/string-width/**", "@aws-cdk/assertions-alpha/table", "@aws-cdk/assertions-alpha/table/**", + "@aws-cdk/aws-amplify-alpha/yaml", + "@aws-cdk/aws-amplify-alpha/yaml/**", "@aws-cdk/assertions/colors", "@aws-cdk/assertions/colors/**", "@aws-cdk/assertions/diff", @@ -93,8 +95,6 @@ "@aws-cdk/assertions/table/**", "@aws-cdk/aws-amplify/yaml", "@aws-cdk/aws-amplify/yaml/**", - "@aws-cdk/aws-amplify-alpha/yaml", - "@aws-cdk/aws-amplify-alpha/yaml/**", "@aws-cdk/aws-codebuild/yaml", "@aws-cdk/aws-codebuild/yaml/**", "@aws-cdk/aws-codepipeline-actions/case", diff --git a/packages/@aws-cdk/aws-amplify/README.md b/packages/@aws-cdk/aws-amplify/README.md index ff2a7a93ae7e2..fd3d5321d02d4 100644 --- a/packages/@aws-cdk/aws-amplify/README.md +++ b/packages/@aws-cdk/aws-amplify/README.md @@ -179,9 +179,9 @@ const amplifyApp = new amplify.App(this, 'MyApp', { }); ``` -## Adding custom headers +## Adding custom response headers -Use the `customHeaders` prop to configure custom headers for an Amplify app: +Use the `customResponseHeaders` prop to configure custom response headers for an Amplify app: ```ts const amplifyApp = new amplify.App(stack, 'App', { @@ -190,19 +190,19 @@ const amplifyApp = new amplify.App(stack, 'App', { repository: '', oauthToken: cdk.SecretValue.secretsManager('my-github-token') }), - customHeaders: [ + customResponseHeaders: [ { pattern: '*.json', - headers: [ - { key: 'custom-header-name-1', value: 'custom-header-value-1' }, - { key: 'custom-header-name-2', value: 'custom-header-value-2' }, - ], + headers: { + 'custom-header-name-1': 'custom-header-value-1', + 'custom-header-name-2': 'custom-header-value-2', + }, }, { pattern: '/path/*', - headers: [ - { key: 'custom-header-name-1', value: 'custom-header-value-2' }, - ], + headers: { + 'custom-header-name-1': 'custom-header-value-2', + }, }, ], }); diff --git a/packages/@aws-cdk/aws-amplify/lib/app.ts b/packages/@aws-cdk/aws-amplify/lib/app.ts index 1e174f09153a5..030dc58059a6e 100644 --- a/packages/@aws-cdk/aws-amplify/lib/app.ts +++ b/packages/@aws-cdk/aws-amplify/lib/app.ts @@ -121,13 +121,13 @@ export interface AppProps { /** - * The custom HTTP headers for an Amplify app. + * The custom HTTP response headers for an Amplify app. * * @see https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html * - * @default - no custom headers + * @default - no custom response headers */ - readonly customHeaders?: CustomHeader[]; + readonly customResponseHeaders?: CustomResponseHeader[]; /** * Custom rewrite/redirect rules for the application @@ -249,7 +249,7 @@ export class App extends Resource implements IApp, iam.IGrantable { name: props.appName || this.node.id, oauthToken: sourceCodeProviderOptions?.oauthToken?.toString(), repository: sourceCodeProviderOptions?.repository, - customHeaders: props.customHeaders ? renderCustomHeaders(props.customHeaders) : undefined, + customHeaders: props.customResponseHeaders ? renderCustomResponseHeaders(props.customResponseHeaders) : undefined, }); this.appId = app.attrAppId; @@ -500,36 +500,26 @@ export class CustomRule { } /** - * Custom header of an Amplify App. + * Custom response header of an Amplify App. */ -export interface CustomHeader { +export interface CustomResponseHeader { /** - * The pattern used to match files to be applied with this header. + * These custom headers will be applied to all URL file paths that match this pattern. */ readonly pattern: string; /** - * The array of custom header options to be applied. + * The map of custom headers to be applied. */ - readonly headers: CustomHeaderOptions[]; + readonly headers: { [key: string]: string }; } -/** - * Options for any custom header for an Amplify App. - */ -export interface CustomHeaderOptions { - /** - * The name of the custom header. - */ - readonly key: string; - - /** - * The value of the custom header. - */ - readonly value: string; -} +function renderCustomResponseHeaders(customHeaders: CustomResponseHeader[]): string { + const modifiedHeaders = customHeaders.map(customHeader => ({ + ...customHeader, + headers: Object.entries(customHeader.headers).map(([key, value]) => ({ key, value })), + })); -function renderCustomHeaders(customHeaders: CustomHeader[]): string { - const customHeadersObject = { customHeaders }; + const customHeadersObject = { customHeaders: modifiedHeaders }; return YAML.stringify(customHeadersObject); } diff --git a/packages/@aws-cdk/aws-amplify/test/app.test.ts b/packages/@aws-cdk/aws-amplify/test/app.test.ts index 2ae1ca5c16ebc..87b15e143ab7f 100644 --- a/packages/@aws-cdk/aws-amplify/test/app.test.ts +++ b/packages/@aws-cdk/aws-amplify/test/app.test.ts @@ -403,19 +403,19 @@ test('with custom headers', () => { repository: 'aws-cdk', oauthToken: SecretValue.plainText('secret'), }), - customHeaders: [ + customResponseHeaders: [ { pattern: '*.json', - headers: [ - { key: 'custom-header-name-1', value: 'custom-header-value-1' }, - { key: 'custom-header-name-2', value: 'custom-header-value-2' }, - ], + headers: { + 'custom-header-name-1': 'custom-header-value-1', + 'custom-header-name-2': 'custom-header-value-2', + }, }, { pattern: '/path/*', - headers: [ - { key: 'custom-header-name-1', value: 'custom-header-value-2' }, - ], + headers: { + 'custom-header-name-1': 'custom-header-value-2', + }, }, ], }); diff --git a/packages/@aws-cdk/aws-amplify/test/integ.app.ts b/packages/@aws-cdk/aws-amplify/test/integ.app.ts index 68fefd0fd3e77..accdaed6840bf 100644 --- a/packages/@aws-cdk/aws-amplify/test/integ.app.ts +++ b/packages/@aws-cdk/aws-amplify/test/integ.app.ts @@ -9,19 +9,19 @@ class TestStack extends Stack { const amplifyApp = new amplify.App(this, 'App', { basicAuth: amplify.BasicAuth.fromGeneratedPassword('aws'), autoBranchCreation: {}, - customHeaders: [ + customResponseHeaders: [ { pattern: '*.json', - headers: [ - { key: 'custom-header-name-1', value: 'custom-header-value-1' }, - { key: 'custom-header-name-2', value: 'custom-header-value-2' }, - ], + headers: { + 'custom-header-name-1': 'custom-header-value-1', + 'custom-header-name-2': 'custom-header-value-2', + }, }, { pattern: '/path/*', - headers: [ - { key: 'custom-header-name-1', value: 'custom-header-value-2' }, - ], + headers: { + 'custom-header-name-1': 'custom-header-value-2', + }, }, ], });