Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion packages/@aws-cdk/aws-amplify-alpha/lib/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,9 @@ export class App extends Resource implements IApp, iam.IGrantable {
name: props.appName || this.node.id,
oauthToken: sourceCodeProviderOptions?.oauthToken?.unsafeUnwrap(), // Safe usage
repository: sourceCodeProviderOptions?.repository,
customHeaders: props.customResponseHeaders ? renderCustomResponseHeaders(props.customResponseHeaders, this) : undefined,
customHeaders: props.customResponseHeaders && props.customResponseHeaders.length > 0
? renderCustomResponseHeaders(props.customResponseHeaders, this)
: undefined,
platform: appPlatform,
jobConfig: props.buildComputeType ? { buildComputeType: props.buildComputeType } : undefined,
});
Expand Down Expand Up @@ -594,7 +596,21 @@ export interface CustomResponseHeader {
readonly headers: { [key: string]: string };
}

/**
* Renders custom response headers to YAML format.
*
* @param customHeaders - Array of custom headers. Must not be empty.
* @param scope - Construct scope for error reporting
* @returns YAML string representation of custom headers
*
* @internal
*/
function renderCustomResponseHeaders(customHeaders: CustomResponseHeader[], scope: IConstruct): string {
// Defensive assertion - should never happen due to call site validation
if (customHeaders.length === 0) {
throw new ValidationError('renderCustomResponseHeaders called with empty array', scope);
}

const hasAppRoot = customHeaders[0].appRoot !== undefined;
const yaml = [hasAppRoot ? 'applications:' : 'customHeaders:'];

Expand Down
20 changes: 19 additions & 1 deletion packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Template } from 'aws-cdk-lib/assertions';
import { Template, Match } from 'aws-cdk-lib/assertions';
import * as codebuild from 'aws-cdk-lib/aws-codebuild';
import * as codecommit from 'aws-cdk-lib/aws-codecommit';
import * as iam from 'aws-cdk-lib/aws-iam';
Expand Down Expand Up @@ -549,6 +549,24 @@ test('error with inconsistent appRoot in custom headers', () => {
}).toThrow('appRoot must be either be present or absent across all custom response headers');
});

test('with empty custom response headers array', () => {
// WHEN - Empty array should be handled gracefully (regression test for #35693)
new amplify.App(stack, 'App', {
sourceCodeProvider: new amplify.GitHubSourceCodeProvider({
owner: 'aws',
repository: 'aws-cdk',
oauthToken: SecretValue.unsafePlainText('secret'),
}),
customResponseHeaders: [],
});

// THEN - CustomHeaders property should be omitted from CloudFormation
Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', {
Name: 'App',
CustomHeaders: Match.absent(),
});
});

test('create a statically hosted app by default', () => {
// WHEN
new amplify.App(stack, 'App', {});
Expand Down
Loading