Routing Traffic to Two CloudFront Distributions on the Same Domain

When deploying multiple web applications that serve different content but share the same domain, it can be useful to route traffic to specific paths and direct users seamlessly between them. This is possible using AWS CloudFront with Amazon Route 53 and AWS Lambda@Edge. In this post, we’ll set up two different CloudFront distributions for two applications on the same domain, configuring them to serve content based on specific URL paths.

Scenario Overview

Let’s say we have:

  • App 1: A primary application hosted on CloudFront Distribution 1, serving content for the /app1 path.
  • App 2: A secondary application hosted on CloudFront Distribution 2, serving content for the /app2 path.

We want users to be able to navigate between /app1 and /app2 smoothly, as if they are using a single integrated site.

What We’ll Use

  1. Amazon Route 53: For domain management and DNS routing.
  2. CloudFront Distributions: Each CloudFront distribution will serve one of the applications.
  3. Lambda@Edge: A Lambda function deployed on the edge, allowing us to intercept requests and direct traffic to the correct distribution based on the URL path.

Step 1: Create CloudFront Distributions for Each Application

First, create two CloudFront distributions in the AWS Management Console, each serving one of your applications (App 1 and App 2).

  1. CloudFront Distribution 1:

    • Origin: Point to the storage bucket or origin server for App 1 (e.g., an S3 bucket or EC2 instance).
    • Path: Serve all content under /app1.
  2. CloudFront Distribution 2:

    • Origin: Point to the storage bucket or origin server for App 2.
    • Path: Serve all content under /app2.

Tip: Make sure both distributions have the necessary caching settings, SSL/TLS certificates, and access policies configured as needed for your applications.

Step 2: Set Up Route 53 to Point to the Distributions

In Route 53, create a hosted zone if you haven’t already, and configure your domain to point to the CloudFront distribution for App 1.

  1. Configure the Domain: Set up a CNAME or alias record pointing your domain (e.g., example.com) to the primary CloudFront distribution (App 1).
  2. Set Up URL Paths: We’ll use Lambda@Edge in the next step to route requests for /app2 to the second CloudFront distribution.

Step 3: Create a Lambda@Edge Function to Route Traffic

To ensure smooth routing between the applications based on URL paths, we’ll create a Lambda@Edge function that intercepts requests and directs them to the appropriate distribution.

Lambda@Edge Function Code

Create a Lambda function in AWS Lambda with the following code:

'use strict';

exports.handler = async (event) => {
    const request = event.Records[0].cf.request;
    const uri = request.uri;

    // Define the hostnames for each CloudFront distribution
    const app1Host = 'app1.example.com'; // CloudFront Distribution 1 hostname
    const app2Host = 'app2.example.com'; // CloudFront Distribution 2 hostname

    // Check the URI and rewrite to the correct distribution
    if (uri.startsWith('/app2')) {
        // Redirect to App 2's distribution for /app2 paths
        request.origin = {
            custom: {
                domainName: app2Host,
                port: 443,
                protocol: 'https',
                path: '', // Ensure that the path remains consistent
                sslProtocols: ['TLSv1.2'],
                readTimeout: 5,
                keepaliveTimeout: 5,
                customHeaders: {},
            },
        };
        request.headers['host'] = [{ key: 'host', value: app2Host }];
    } else {
        // Default to App 1's distribution for all other paths
        request.origin = {
            custom: {
                domainName: app1Host,
                port: 443,
                protocol: 'https',
                path: '',
                sslProtocols: ['TLSv1.2'],
                readTimeout: 5,
                keepaliveTimeout: 5,
                customHeaders: {},
            },
        };
        request.headers['host'] = [{ key: 'host', value: app1Host }];
    }

    return request;
};

Deploy the Lambda Function to CloudFront

After creating the Lambda function, deploy it to CloudFront as a Lambda@Edge function:

  1. Attach Lambda@Edge: In the CloudFront settings for Distribution 1 (App 1’s distribution), go to the Behaviors section.
  2. Select Behavior: Choose the behavior that matches your main path (e.g., / or /app1).
  3. Associate Lambda@Edge Function: Attach the Lambda@Edge function to the Origin Request event.

This will ensure that any requests are intercepted and routed to the correct CloudFront distribution based on the URL path.

Step 4: Test the Routing

With everything set up, it’s time to test the routing:

  1. Test App 1: Go to https://example.com/app1. You should see content served from CloudFront Distribution 1 (App 1).
  2. Test App 2: Go to https://example.com/app2. This should redirect you to CloudFront Distribution 2 (App 2).

Both applications should now be accessible under the same domain but served by different CloudFront distributions, enabling smooth navigation between them.

Additional Tips for a Smooth User Experience

  • Consistent Styling: To maintain a seamless experience, ensure that both applications have consistent design and navigation elements.
  • Shared State Management: If users need to switch between applications while retaining state (like user sessions), consider setting up a shared state using cookies or a common API.
  • SSL/TLS Certificates: Use the same SSL/TLS certificate for both distributions to avoid browser warnings.

Conclusion

By using Lambda@Edge with AWS CloudFront and Route 53, you can route traffic between two applications under the same domain and specific URL paths. This setup provides a smooth and integrated user experience while keeping deployment flexible and manageable. This approach is useful for multi-app architectures or for gradually rolling out new sections of a website on separate stacks.

Published: Nov 4, 2024