How do I set up API Gateway with my own CloudFront distribution?

Last updated: 2020-08-07

I want an edge-optimized API endpoint in Amazon API Gateway, but I need more control over the Amazon CloudFront distribution. Can I create and use my own distribution?

Short description

If your API clients are geographically dispersed, you might want an edge-optimized API endpoint in API Gateway. This type of endpoint acts like a regional endpoint, but has an AWS managed CloudFront web distribution in front of it to help improve the client connection time.

However, you can get the benefit of the global CloudFront content delivery network while keeping more control over the distribution. For this setup, use a regional API with a custom CloudFront distribution manually assigned in front of it.

Resolution

Create a regional API in API Gateway, and then follow these instructions.

Set up a GET method for your API

  1. In the API Gateway console, choose the name of your new regional API.
  2. In the Resources pane, choose Actions, and then choose Create Method.
  3. Choose GET from the list that appears under the / resource node, and then choose the check mark icon.
  4. In / - GET - Setup, for Integration type, choose Mock, and then choose Save. A mock integration responds to any request that reaches it, which helps later with testing.

Deploy your API and get the invoke URL

  1. Deploy your API to a stage.
  2. At the top of the Stage Editor pane, copy the Invoke URL to your clipboard. The URL looks like this:
    https://restApiId.execute-api.region.amazonaws.com/stageName.

Test your API

Test your API's invoke URL for a "200" HTTP status code by using the API Gateway console, the Postman app, or curl from a command line interface. For more information about curl, see the curl project website.

Using curl, do either of the following:

Note: In these commands, replace https://restApiId.execute-api.region.amazonaws.com/stageName with your API's invoke URL.

In Linux, run this command:

curl -IX GET https://restApiId.execute-api.region.amazonaws.com/stageName

In Windows PowerShell, run this command:

curl https://restApiId.execute-api.region.amazonaws.com/stageName

Note: If you get a status code other than "200," verify that you deployed the API to your stage in the console. Also, verify that you specified the stage in the URL.

Create a CloudFront web distribution

  1. In the CloudFront console, choose Create Distribution.
  2. On the Select a delivery method for your content page, under Web, choose Get Started.
  3. On the Create Distribution page, for Origin Domain Name, paste your API's invoke URL, but remove the stage name. For example:
    https://1a2bc3d456.execute-api.us-east-1.amazonaws.com
  4. For Origin Path, enter your API's stage name with a slash in front of it (/stageName). Or, if you want to enter the stage name yourself when invoking the URL, don't enter an Origin Path.
    Note: If you enter an incorrect stage name for Origin Path, you can get an error when invoking the CloudFront distribution. For example, an unauthorized request error that returns the message "Missing Authentication Token" and a 403 Forbidden response code.
  5. For Minimum Origin SSL Protocol, it's a best practice to choose TLSv1.2 only. Don't choose SSLv3. API Gateway doesn't support that protocol.
  6. For Origin Protocol Policy, choose HTTPS Only.
    Note: API Gateway doesn't support unencrypted (HTTP) endpoints. For more information, see Amazon API Gateway FAQs.
  7. (Optional) To forward custom headers to your origin, enter one or more custom headers for Origin Custom Headers.
    Note: There are several custom headers that CloudFront can't forward to your origin.
  8. If you enabled IAM authentication on your API, or you plan to enable it later, you must add the Authorization request header to an allow list. For Cache Based on Selected Request Headers, choose Whitelist. For Whitelist Headers, add Authorization to the list of allowed headers.
    Important: If you change the Cache Based on Selected Request Headers setting to All, or if you allow the Host header, then your setup won't work. For more information, see Caching content based on request headers.
  9. (Optional) To use your own custom domain names for the distribution instead of the one CloudFront assigns to it, enter one or more domain names for Alternate Domain Names (CNAMEs). For more information, see Using custom URLs for files by adding alternate domain names (CNAMEs).
  10. (Optional) Configure any additional settings that you want to customize.
  11. Choose Create Distribution.
  12. Wait for your distribution to deploy. This can take 15-20 minutes. When its Status appears as Deployed in the console, the distribution is ready.

For more information, see Creating a distribution.

Test your CloudFront web distribution

  1. In the CloudFront console, note the Domain Name of your distribution. If you didn't use a custom domain name, the domain looks like this: a222222bcdefg5.cloudfront.net.
  2. Test the domain name for a "200" HTTP status code using either of the commands mentioned previously in the Test your API section.
    Note: If you enabled IAM authentication on a method for a particular API resource, you must append the resource name to the end of the distribution domain name when invoking your API. The full invoke URL with resource name looks like either of these URLs, depending on whether you entered an Origin Path while creating the distribution: https://distributionDomainName/resourceName or https://distributionDomainName/stageName/resourceName. For more information on testing for this use case, see How do I enable IAM authentication for API Gateway APIs?

Note: If you get a "500" server error code, the distribution might not be fully deployed. If you get no response, the CloudFront DNS record might not have fully propagated yet. In either case, verify that it's been 15-20 minutes since you created your distribution, and then retry the procedure.

Your API now uses the distribution that you created, and you can access any resources on the API using the CloudFront URL.