Serve multiple website hosted on s3 via Cloudfront and Lambda@edge

Serve multiple website hosted on s3 via Cloudfront and Lambda@edge

You have two domains ( example1.com and example2.com) served by a single CloudFront distribution. Both domains' content is hosted in separate S3 buckets. You want to use a Lambda@Edge function to inspect incoming requests and route them to the correct S3 bucket based on the domain.

Step 1: Set Up Your S3 Buckets

Ensure your S3 buckets are set up to host your websites. Each bucket should contain the content for one of your domains. Remember, S3 bucket names don't need to match your domain names since routing will be handled by Lambda@Edge.

Step 2: Create a Lambda@Edge Function

  1. Open AWS Lambda: Go to the AWS Lambda console and create a new Lambda function. Note that for Lambda@Edge, your function must be created in the N. Virginia (us-east-1) region.

  2. Select Blueprint: If available, use the cloudfront-modify-request-header blueprint as a starting point, or start from scratch.

  3. Configure the Function:

    • Write the function code to inspect the Host header and modify the request URI or origin based on the domain. Here's a simplified example in Node.js:

        javascriptCopy code
        'use strict';
      
        exports.handler = (event, context, callback) => {
            const request = event.Records[0].cf.request;
            const headers = request.headers;
      
            // Check the Host header to determine the domain
            const hostHeader = headers['host'][0].value;
      
            if (hostHeader === 'example1.com') {
                // Route to the S3 bucket for example1.com
                request.origin = {
                    s3: {
                        domainName: 'example1-bucket.s3.amazonaws.com',
                        region: '',
                        authMethod: 'none',
                        path: '',
                        customHeaders: {}
                    }
                };
                request.headers['host'] = [{ key: 'host', value: 'example1-bucket.s3.amazonaws.com' }];
            } else if (hostHeader === 'example2.com') {
                // Route to the S3 bucket for example2.com
                request.origin = {
                    s3: {
                        domainName: 'example2-bucket.s3.amazonaws.com',
                        region: '',
                        authMethod: 'none',
                        path: '',
                        customHeaders: {}
                    }
                };
                request.headers['host'] = [{ key: 'host', value: 'example2-bucket.s3.amazonaws.com' }];
            }
      
            // Return the modified request
            callback(null, request);
        };
      
    • Remember to adjust the domainName values to match your actual S3 bucket names.

  4. Deploy the Function: Deploy your Lambda function in the AWS Lambda console.

  5. Add Permissions: Ensure your Lambda function has the necessary IAM permissions to be executed by CloudFront.

Step 3: Associate Lambda Function with CloudFront

  1. Open CloudFront: Go to the CloudFront console and select your distribution.

  2. Add Lambda Function to Distribution:

    • Navigate to the Behaviors tab, and choose the behavior you want to associate with your Lambda function.

    • Scroll down to the Lambda Function Associations section, and add your Lambda function ARN. Choose the Origin Request event type.

  3. Deploy Changes: Save changes to your distribution. It may take some time for the changes to propagate.

Step 4: Test Your Configuration

After your changes have propagated, test accessing your content through both domains. Each domain should serve content from its respective S3 bucket, as routed by your Lambda@Edge function.

Considerations

  • Testing: Lambda@Edge functions can be challenging to debug due to their execution at edge locations. Use CloudWatch Logs to monitor and debug the function.

  • Performance: Keep in mind the performance implications of using Lambda@Edge. While it offers powerful customization capabilities, it also introduces additional execution time to requests.

  • Costs: Be aware of the costs associated with Lambda@Edge invocations, especially if your sites have high traffic.