When creating the Simple Web Service in the CDK we got an output that was API Gateways unique random domain. This is not a useful domain for a production system as we often want to place the API’s behind a custom domain name.
This article will look at how to create the infrastructure needed with Infrastructure as Code and the AWS CDK to hook up an API Gateway with a custom domain name. The Article assumes your domain is already registered on AWS with a Hosted Zone.

The example API will be a simple Lambda function that returns Hello World to the caller.
First to create the API, this will be a simpler version of The Simple Web Service and just has our Lamnda and the API Gateway hooked together under /v1/hello as a GET method.
// Node Lambda Function
const lambdaFn = new lambdaNode.NodejsFunction(this, 'LambdaFunctionHandler', {
runtime: lambda.Runtime.NODEJS_14_X,
entry: 'lambda/helloWorld.ts',
handler: 'main',
timeout: Duration.seconds(3),
bundling: {
externalModules: [
],
nodeModules: [
],
minify: true
},
environment: {
region: process.env.CDK_DEFAULT_REGION!,
}
});
// API Gateway
const gateway = new apigw.RestApi(this, 'ApiGAteway');
const version = gateway.root.addResource('v1');
const api = version.addResource('hello');
// enable cors
api.addCorsPreflight({
allowOrigins: apigw.Cors.ALL_ORIGINS
});
// Integration of lambda
const lambdaIntegration = new apigw.LambdaIntegration(lambdaFn);
// Add the Lambda as a GET method
api.addMethod('GET', lambdaIntegration)
The Lambda Function code (lambda/helloWorld.ts) will also be simple, just returning a 200, Hello World message.
import { Context, Callback } from 'aws-lambda';
import {DynamoDB} from 'aws-sdk';
export async function main(event: any, _context: Context, callback: Callback) {
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: "Hello World"
};
}
Now for the Custom Domain. First, we must add our domain name as it is in the hosted zone. We can also set the domain name part; this will give us the sub domain.
// Add Custom Domain for API gateway
const domainName = 'AddDomainName.com'; // MODIFY THIS WITH YOUR DOMAIN NAME!
const certDomainName = `*.${domainName}`; // Cirtificate will be generated for *.AddDomainName.com
const domainNamePart = 'test'; // this will add a subdomain eg. test.AddDomainName.com
Once the custom domain parameters have been set we can get the hosted zone looked up by its domain name.
// Get the zone by the domain name
const zone = route53.HostedZone.fromLookup(this, 'HostedZone', { "domainName": domainName });
The zone is then used in creating the SSL certificate. We pass the domain name as the cert domain name not the base domain name as this will be a wild card domain name.
// Create New Wild Card Certificate
const certVal = new cert.DnsValidatedCertificate(this, 'Certificate', {
hostedZone: zone,
domainName: certDomainName,
region: 'us-east-1',
});
Now we have a certificate we can create the custom domain itself. The domain will be made up of the sub domain and base domain. We will also set the endpoint type to EDGE; this is optimised for geographically distributed clients. We also set the security policy to use TLS 1.2
const customDomain = new apigw.DomainName(this, 'customDomain', {
domainName: ( domainNamePart + '.' + domainName ),
certificate: cert.Certificate.fromCertificateArn(this, 'ACM_Certificate', certVal.certificateArn),
endpointType: apigw.EndpointType.EDGE,
securityPolicy: apigw.SecurityPolicy.TLS_1_2
});
Now we have created the domain we can add the base path mapping to connect the API gateway with the custom domain created.
const basePathMap = new apigw.BasePathMapping(this, 'CustomBasePathMapping', {
domainName: customDomain,
restApi: gateway
});
Finally, we must add the CName record to the hosted zone for this domain name part and the custom domain.
const r53Record = new route53.CnameRecord(this, 'ApiGatewayRecordSet', {
zone: zone,
recordName: domainNamePart,
domainName: customDomain.domainNameAliasDomainName
});
Now we can build and deploy the stack, The api can easily be tested by going to the browser and hitting https://%5Bsubdomain%5D.%5B base domain]/v1/hello or by doing a GET request in a tool like postman.

Checkout the Stack on GitHub
Categories: AWS
Leave a Reply