From 88a4da2ea21511d4d396aac5ce9117fd92a296b4 Mon Sep 17 00:00:00 2001 From: mbfreder Date: Tue, 14 May 2024 11:58:04 -0700 Subject: [PATCH] Add domainName prop to FunctionUrl --- packages/aws-cdk-lib/aws-lambda/README.md | 9 +++++++ .../aws-lambda/lib/function-url.ts | 16 +++++++++++- .../aws-lambda/test/function-url.test.ts | 26 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-lambda/README.md b/packages/aws-cdk-lib/aws-lambda/README.md index 5a876c8ae68eb..6c7010617f569 100644 --- a/packages/aws-cdk-lib/aws-lambda/README.md +++ b/packages/aws-cdk-lib/aws-lambda/README.md @@ -480,6 +480,15 @@ new CfnOutput(this, 'TheUrl', { value: fnUrl.url, }); ``` +To get the domain name from the function url, simply call `domainName` on the `FunctionUrl` construct: +```ts +... + +new CfnOutput(this, 'TheDomainName', { + value: fnUrl.domainName, +}); +``` +The .domainName attribute will return the domain name (the function url, without the scheme and the trailing slash). For example, if fnUrl.url returns `https://*******.lambda-url.ap-southeast-2.on.aws/`, then fnUrl.domainName will return `*******.lambda-url.ap-southeast-2.on.aws`. Calls to this URL need to be signed with SigV4. diff --git a/packages/aws-cdk-lib/aws-lambda/lib/function-url.ts b/packages/aws-cdk-lib/aws-lambda/lib/function-url.ts index bed33ec8bae4f..879738646dbb1 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/function-url.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/function-url.ts @@ -4,7 +4,7 @@ import { IFunction } from './function-base'; import { IVersion } from './lambda-version'; import { CfnUrl } from './lambda.generated'; import * as iam from '../../aws-iam'; -import { Duration, IResource, Resource } from '../../core'; +import { Duration, Fn, IResource, Resource } from '../../core'; /** * The auth types for a function url @@ -133,9 +133,17 @@ export interface IFunctionUrl extends IResource { * The url of the Lambda function. * * @attribute FunctionUrl + * For example `https://*******.lambda-url.ap-southeast-2.on.aws/` */ readonly url: string; + /** + * The domain name of the Lambda Function URL + * + * For example `*******.lambda-url.ap-southeast-2.on.aws` + */ + readonly domainName: string; + /** * The ARN of the function this URL refers to * @@ -243,6 +251,12 @@ export class FunctionUrl extends Resource implements IFunctionUrl { } } + get domainName(): string { + return Fn.select( + 0, Fn.split('/', Fn.select(1, Fn.split('https://', this.url))), + ); + } + public grantInvokeUrl(grantee: iam.IGrantable): iam.Grant { return this.function.grantInvokeUrl(grantee); } diff --git a/packages/aws-cdk-lib/aws-lambda/test/function-url.test.ts b/packages/aws-cdk-lib/aws-lambda/test/function-url.test.ts index 048fcea4fa1fa..2d936db84393c 100644 --- a/packages/aws-cdk-lib/aws-lambda/test/function-url.test.ts +++ b/packages/aws-cdk-lib/aws-lambda/test/function-url.test.ts @@ -118,6 +118,32 @@ describe('FunctionUrl', () => { }); }); + test('function url domain name', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('hello()'), + handler: 'index.hello', + runtime: lambda.Runtime.NODEJS_14_X, + }); + const aliasName = 'prod'; + const alias = new lambda.Alias(stack, 'Alias', { + aliasName, + version: fn.currentVersion, + }); + + // WHEN + const url = new lambda.FunctionUrl(stack, 'FunctionUrl', { + function: alias, + }); + + // THEN + const resolved = stack.resolve(stack.toJsonString({ token: url.domainName })); + expect(resolved).toEqual({ + 'Fn::Join': ['', ['{"token":"', { 'Fn::Select': [0, { 'Fn::Split': ['/', { 'Fn::Select': [1, { 'Fn::Split': ['https://', { 'Fn::GetAtt': ['FunctionUrl84B92DCA', 'FunctionUrl'] }] }] }] }] }, '"}']], + }); + }); + test('throws when configured with Version', () => { // GIVEN const stack = new cdk.Stack();