在同一URL下在S3 + Cloudfront上托管多个SPA Web应用程序 [英] Hosting multiple SPA web apps on S3 + Cloudfront under same URL

本文介绍了在同一URL下在S3 + Cloudfront上托管多个SPA Web应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个静态Web应用程序(create-react-apps),它们当前位于两个单独的S3存储桶中.将两个存储桶都配置为公共读取+静态Web托管,并且访问它们的S3托管URL会正确显示站点.

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 their S3 hosted URLs correctly display the sites.

Bucket 1 - First App:
   index.html
   static/js/main.js

Bucket 2 - Second App:
   /secondapp/
       index.html
       static/js/main.js

我为此设置了一个Cloudfront-默认的Cloudfront源正确加载了FirstApp,因此www.mywebsite.com默认加载了index.html.

I have setup a single Cloudfront for this - The default cloudfront origin loads FirstApp correctly, such that www.mywebsite.com loads the index.html by default.

对于SecondApp,我已经设置了缓存行为",以便路径模式secondapp/*指向SecondApp存储桶URL.

For the SecondApp, I have set up a Cache Behavior so that the path pattern secondapp/* points to the SecondApp bucket URL.

在我的浏览器中,当我访问www.mywebsite.com/secondapp/时,它会正确显示第二个Web应用程序.

In my browser, when I visit www.mywebsite.com/secondapp/ it correctly displays the second web app.

但是,如果我省略了斜杠,我会看到"First App",这是不希望的. 如果我访问www.mywebsite.com/secondapp/something,还会看到我不想要的First App. (我希望它加载secondapp的.html)

If I omit the trailing slash however, I instead see the First App, which is undesired. If I visit www.mywebsite.com/secondapp/something, I am also shown the First App, which is also undesired. (I want it to load the .html of secondapp)

两个应用都配置为通过react-router-dom使用html5推送状态.

Both apps are configured to use html5 push state via react-router-dom.

我想要的行为是,访问以下内容会显示正确的网站/存储桶:

My desired behavior is that visiting the following displays the correct site/bucket:

www.mywebsite.com-当前正在工作

www.mywebsite.com/secondapp/-当前正在工作

www.mywebsite.com/secondapp-(不带斜杠)不起作用,显示第一个应用程序

www.mywebsite.com/secondapp - (Without trailing slash) Not working, shows First App

www.mywebsite.com/secondapp/something_else-无法正常运行,请显示第一个应用

www.mywebsite.com/secondapp/something_else - Not working, show First App

如何实现所需的行为?

谢谢!

推荐答案

研究了此问题之后,我能够使用lambda @ edge(

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

通过部署简单的javascript函数将特定路径路由到所需的s3存储桶,我们可以实现类似nginx的路由设置. 该函数位于我们的Cloudfront CDN上的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"

我的设置如下:

  • 我使用了一个s3存储桶,并将第二个应用程序部署在子文件夹"second-app"中
  • 我创建了一个新的Lambda函数,该函数托管在美国东弗吉尼亚北部"上.该区域在这里很重要,因为您只能在该区域中托管lambda函数@edge.
  • 有关实际的Lambda函数,请参见下文
  • 创建后,转到您的CloudFront配置并转到行为>选择默认(*)路径模式,然后单击编辑"
  • 滚动到有"Lambda函数关联"的底部
  • 从下拉列表中选择来源请求"
  • 输入您的lambda函数(arn:aws:lambda:us-east-1:12345667890:function:my-function-name)的地址
  • 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)

这是我使用的lambda函数的示例.

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?

这篇关于在同一URL下在S3 + Cloudfront上托管多个SPA Web应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆