Configure a Custom Domain for AWS API Gateway

Photo by Jens Lelie on Unsplash

Categories

  • Serverless
  • Howto

In previous blog posts I’ve shown how to build serverless microservices which provide a REST API. Each service consists of a bunch of Lambda functions triggered by the AWS API Gateway. In a real world scenario multiple microservices would compose an application exposed through a single domain like api.example.com. For the consumer of the API it should not be transparent that the services offered by the API are actually broke up in multiple microservices.

How can this be done when AWS API Gateway is used?

Actually, it’s pretty easy to do. The key is to use the custom domain feature of API Gateway. Additionally, the domain and associated DNS record needs to be set up. For this task, I’ve created a simple CloudFormation template:

AWSTemplateFormatVersion: 2010-09-09

Parameters:

  HostedZoneId:
    Type: AWS::Route53::HostedZone::Id
  Domain:
    Type: String

Resources:

  DomainName:
    Type: AWS::ApiGateway::DomainName
    Properties:
      CertificateArn:
        Ref: Certificate
      DomainName:
        Ref: Domain
      EndpointConfiguration:
        Types:
          - EDGE
      SecurityPolicy: TLS_1_2

  Certificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName:
        Ref: Domain
      ValidationMethod: DNS
      DomainValidationOptions:
        - DomainName:
            Ref: Domain
          HostedZoneId:
            Ref: HostedZoneId

  RecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId:
        Ref: HostedZoneId
      Name:
        Ref: Domain
      Type: A
      AliasTarget:
        HostedZoneId:
          Fn::GetAtt: DomainName.DistributionHostedZoneId
        DNSName:
          Fn::GetAtt: DomainName.DistributionDomainName

Outputs:

  DomainName:
    Description: The Domain name
    Value:
      Ref: Domain
    Export:
      Name:
        Fn::Sub: ${AWS::StackName}-DomainName

With this, the custom domain is configured for AWS API Gateway. The final step is to map a microservice to this domain. This is done by configuring the base path mapping. It provides the connection to the various API instances for each service. The important part is that each service has it’s own namespace expressed as a path.

For each microservice the configuration needs to be extended to extended to integrate with the custom domain. The following configuration needs to be added

BasePathMapping:
  Type: AWS::ApiGateway::BasePathMapping
  Properties:
    BasePath: tasks
    DomainName:
      Fn::ImportValue:
        Fn::Sub: ${ApiDomainStackName}-DomainName
    RestApiId:
      Ref: RestApi
    Stage:
      Ref: StageName

This setup makes it pretty easy to encapsulate the various microservices that make up an application behind a common domain. Additionally, it’s also possible to configure common cross-functional requirements across all of the services, like authentication, throttling, API keys, etc.

Following the principles and techniques outlined in this post make it possible to easily hide a microservice application behind an AWS API Gateway.