Path-based Routing on AWS CloudFront — Host Multiple Apps on The Same Domain

Use Case

Up until a couple of weeks ago, I was hosting my portfolio web page (which is a simple web app with an index page, a few CSS files, a few JavaScript files) on an S3 bucket configured as a static website living behind CloudFront for domain mapping “hishri.com”.

Then I decided to set up a small Jekyll blog which I deployed by connecting Amplify to the git repo of my new blog. Now my blog is available on a URL like this master.d7z2wvxxxx.amplifyapp.com.

Now I want my blog to be also available under my domain: hishri.com/blog.

Amplify supports setting custom domains using the Domain management configuration. That is not an option in this case, since my domain is already set up to point to CloudFront (diagram above).

This issue can be solved by setting another unused domain or even sub-domain for example “blog.hishri.com”.

Elastic Load Balancers allow path-based routing for EC2 instances and VPC IP addresses, but they do not support other AWS resources.

Enter CloudFront Origins & Cache Behaviors

What if we can tell cloudFront to serve my Amplify blog app when visitors request hishri.com/blog, and serve the S3 web app when visitors request hishri.com.

CloudFront-level routing architecture

CloudFront compares a request for an object with the path patterns in your cache behaviors based on the order of the cache behaviors in your distribution.

Adding Amplify CloudFront Origins

The first step is to add another origin to my CloudFront Destribution.

You will notice in the first diagram that my CloudFront had one origin which is my S3 static website URL buckxxxx.s3-website-eu-central-1.amazonaws.com.

My CloudFront Distribution

I created a new origin under “Origins” which will point to my blog amplify app’s URL

CloudFront Distribution Origin creation

Now we have two origins that we can route to!

Setting CloudFront Cache Behaviors

Now let’s move to the next tab “Behaviors” and create a new behavior for the blog!

We will set a origin, the new origin that we created earlier, it should appear in the drop-down list.

Now our CloudFront Distribution has 2 origins and is configured to serve the origin based on the route chosen by user!

CloudFront Behaviors

The order is IMPORTANT. Since the default behavior (* wildcard) includes any path, we need to handle the “blog” path first otherwise it will be never reached.

First Result

Now we go to our blog by visiting “hishri.com/blog” .. and

Access Denied page from Amplify

What am I seeing this?

Another small detail that we should know is that CloudFront will append the path to the amplify URL.

In this case since we are mapping /blog to the amplify URL, CloudFront will serve {amplify app origin URL}/blog which might not exist if our app is not under that path on Amplify.

Solution

Let’s go to our Amplify app and modify the build settings configuration amplify.yml.

For Jekyll, here is my amplify.yml file

version: 1
frontend:
phases:
preBuild:
commands:
- bundle install
build:
commands:
- bundle exec jekyll b
- mkdir blog
- mv _site/* blog/
- mv blog _site/
postbuild:
commands:
- echo "post build"
artifacts:
baseDirectory: _site
files:
- '**/*'
cache:
paths: []

What I am doing, is moving the generated site (Jekyll generates the site files and puts them under the _site folder) into a folder called “blog”

that way my site is available under {amplify app url/blog}

Let’s try again

My blog living in amplify!

I hope you guys found this helpful!

Here is my portfolio and Github!

Taha HICHRI (hishri.com)

tahaHichri (Taha HICHRI) · GitHub

The machine thinks. hishri.com