Search code examples
amazon-web-servicesflaskaws-api-gatewayamazon-cloudfrontdomain-mapping

Use Cloudfront to remove {stage} from custom domain url


I have a flask app deployed to AWS Lambda via zappa. Zappa creates an AWS rest endpoint such as random_api_ID.execute-api.us-east-2.amazonaws.com/devwhich works perfectly when directly entered into the browser. But, when I use Cloudfront to associate this end point to my custom domain, dev.mywebsite.com, I get a 404 error in the response for any assets stored in a subfolder. The reason is because Cloudfront is serving urls such as

dev.mywebsite.com/dev/static/css/style.css

instead of

dev.mywebsite.com/static/css/style.css

Also, this works: random_api_ID.execute-api.us-east-2.amazonaws.com/dev/static/css/style.css

But this does not: random_api_ID.execute-api.us-east-2.amazonaws.com/static/css/style.css

So, somehow, I need Cloudfront to associate random_api_ID.execute-api.us-east-2.amazonaws.com/dev with dev.mywebsite.com instead of dev.mywebsite.com/dev.

My Cloudfront distribution has the following parameters:

 Alternate Domain Name: dev.mywebsite.com 
 Origin Domain: random_api_ID.execute-api.us-east-2.amazonaws.com
 Origin Path: dev <-- this is the stage name

I've tried mapping a custom domain to the zappa-generated AWS rest endpoint via AWS API Gateway; however, that solution produces a private Cloudfront domain that I have no control over; I prefer a solution that involves configuring Cloudfront.

Thanks in advance!


Solution

  • I found this article and ended up solving the problem by using Cloudfront Functions:

    1. Make sure you have a Cloudfront distribution that's a) associated with your AWS API Gateway endpoint and b) contains your custom domain name.

    2. Within the origin tab of your distribution, I entered the full AWS API Gateway endpoint. My app uses an endpoint automatically generated by Zappa,random_api_ID.execute-api.us-east-2.amazonaws.com/dev. Entering the full endpoint into the origin domain field should automatically populate the origin path field with \dev.

    3. In the Cloudfront navigation pane, choose Functions then click the Create function button.

    4. Enter a function nam, then click Create Function.

    5. With the Build tab selected, go to the Function Code section and enter the following Javascript:

      function handler(event) {
          var request = event.request;
          request.uri = request.uri.replace(/^\/[^/]*\//, "/"); 
          return request;
      }
      

    enter image description here

    1. Save your function

    2. Test your function by clicking the Test tab and enter a url with an appended stage name:

    enter image description here

    1. Clicking the test function button. You should get a successful execution message below your function code:

    enter image description here

    1. Click the Publish tab and publish your function by clicking the Publish function button.

    2. Under the publish section, you need to associate the published function to your Cloudfront distribution. Click the Add distribution button.

    3. In the new window, select a distribution and click the Add Association button.

    enter image description here

    1. Wait for Cloudfront to finish deploying your distribution. When it's finished, check your custom domain in the browser and make sure assets are successfully loaded.