Cloudformation: HTTP API Gateway with DNS
Tags: aws
Published: 2021-09-08 16:23:05

##Hey, Welcome!
In this post I am going to share how you can quickly setup a cloudformation stack with an HTTP API Gateway listening behind a custom domain.

To make it simpler, I will break it down into multiple steps.

If you are just interested in the `yaml` template simply scroll down to the end.

**Step 1: Create an HTTP api gateway resource**

```yaml
  DemoApiGateway:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: Get started HTTP API
      ProtocolType: HTTP
```

The above code creates an [api gateway] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-api.html) resource.
I chose HTTP API over REST because of the following reasons:

* low latency
* cost effective

You can read more about the [comparison here] (https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html)

**Step 2: Create an api gateway stage**

```yaml
  DemoApiStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      ApiId: !Ref DemoApiGateway
      StageName: Live
      Description: Live Stage
      AutoDeploy: true
```

The above code creates an [api stage] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-stage.html) called `Live` and it is set to auto deploy.

**Step 3: Create custom domain**

```yaml
  DemoDomainName:
    Type: AWS::ApiGatewayV2::DomainName
    Properties:
      DomainName: [YOUR-DOMAIN-NAME]
      DomainNameConfigurations:
        - EndpointType: REGIONAL
          CertificateArn: [YOUR-ACM-CERT-ARN]
```

The above code creates a [custom domain] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-domainname.html) resource that will be attached to the API Gateway.

Please note, you need to create an ACM certificate which is available in the same region since the endpoint type is `REGIONAL`

**Step 4: Create domain mapping**

```yaml
  DemoApiMapping:
    Type: AWS::ApiGatewayV2::ApiMapping
    Properties:
      DomainName: [YOUR-DOMAIN-NAME]
      ApiId: DemoApiGateway
      Stage: DemoApiStage
```

The above code creates [domain mapping] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-apimapping.html) resource that connects the domain to the api gateway on a given stage name.

**Step 5: Create DNS alias record**

```yaml
  DemoRecordSetGroup:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneId: [YOUR-HOSTED-ZONE-ID]
      RecordSets:
        - Name: [YOUR-DOMAIN-NAME]
          Type: A
          AliasTarget:
            DNSName: !GetAtt DemoDomainName.RegionalDomainName
            HostedZoneId: !GetAtt DemoDomainName.RegionalHostedZoneId
```

The above code creates an [alias target] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53-recordsetgroup.html) of type `A` in route53 for the given hosted zone ID and given domain name.

That is all you need to create an HTTP api gateway with custom domain.

You can use the below template to create cloudformation stack with all the above resources we talked about.

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: HTTP API Gateway stack

Resources:
  DemoApiGateway:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: Demo API Gateway
      ProtocolType: HTTP

  DemoApiStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      ApiId: !Ref DemoApiGateway
      StageName: live
      Description: Live Stage
      AutoDeploy: true

  DemoApiDomainName:
    Type: AWS::ApiGatewayV2::DomainName
    Properties:
      DomainName: [YOUR-DOMAIN-NAME]
      DomainNameConfigurations:
        - EndpointType: REGIONAL
          CertificateArn: [YOUR-ACM-CERTIFICATE-ARN]

  DemoApiBasePathMapping:
    Type: AWS::ApiGatewayV2::ApiMapping
    Properties:
      DomainName: [YOUR-DOMAIN-NAME]
      ApiId: !Ref DemoApiGateway
      Stage: !Ref DemoApiStage

  DemoRecordSetGroup:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneId: [YOUR-HOSTED-ZONE-ID]
      RecordSets:
        - Name: [YOUR-DOMAIN-NAME]
          Type: A
          AliasTarget:
            DNSName: !GetAtt DemoApiDomainName.RegionalDomainName
            HostedZoneId: !GetAtt DemoApiDomainName.RegionalHostedZoneId
```

In my next post, I will be sharing how we can connect a lambda function to our `DemoApiGateway`