Hosting multiple SPA web apps on S3 + Cloudfront under same URL

后端 未结 1 966
孤城傲影
孤城傲影 2021-02-20 03:23

I have two static web apps (create-react-apps) that are currently in two separate S3 buckets. Both buckets are configured for public read + static web hosting, and visiting thei

1条回答
  •  粉色の甜心
    2021-02-20 03:40

    After researching this issue, I was able to resolve it using lambda@edge (https://aws.amazon.com/lambda/edge/)

    By deploying a simple javascript function to route specific paths to the desired s3 bucket, we are able to achieve an nginx-like routing setup. The function sits on lambda@edge on our Cloudfront CDN, meaning you can specify when it is triggered. For us, it's on "Origin Request"

    My setup is as follows:

    • I used a single s3 bucket, and deployed my second-app in a subfolder "second-app"
    • I created a new Lambda function, hosted on "U.S. East N Virginia". The region is important here, as you can only host lambda function an @edge in this region.
    • See below for the actual Lambda function
    • Once created, go to your CloudFront configuration and go to "Behaviors > Select the Default (*) path pattern and hit Edit"
    • Scroll to the bottom where there is "Lambda Function Associations"
    • Select "Origin Request" form the drop down
    • Enter the address for your lambda function (arn:aws:lambda:us-east-1:12345667890:function:my-function-name)

    Here is an example of the lambda function I used.

    
    var path = require('path');
    
    exports.handler = (event, context, callback) => {
      // Extract the request from the CloudFront event that is sent to Lambda@Edge
      var request = event.Records[0].cf.request;
    
      const parsedPath = path.parse(request.uri);
    
      // If there is no extension present, attempt to rewrite url
      if (parsedPath.ext === '') {
        // Extract the URI from the request
        var olduri = request.uri;
    
        // Match any '/' that occurs at the end of a URI. Replace it with a default index
        var newuri = olduri.replace(/second-app.*/, 'second-app/index.html');
    
        // Replace the received URI with the URI that includes the index page
        request.uri = newuri;
      }
      // If an extension was not present, we are trying to load static access, so allow the request to proceed
      // Return to CloudFront
      return callback(null, request);
    };
    

    These are the resources I used for this solution:

    • https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
    • https://github.com/riboseinc/terraform-aws-s3-cloudfront-website/issues/1
    • How do you set a default root object for subdirectories for a statically hosted website on Cloudfront?

    0 讨论(0)
提交回复
热议问题