在同一网址下的S3 + Cloudfront上托管多个SPA网络应用

问题描述 投票:2回答:1

我有两个静态网络应用程序(create-react-apps),目前在两个独立的S3存储桶中。两个存储桶都配置为公共读取+静态Web托管,访问其S3托管URL正确显示网站。

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

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

我为此设置了一个Cloudfront - 默认的cloudfront origin正确加载FirstApp,这样www.mywebsite.com默认加载index.html。

对于SecondApp,我设置了一个缓存行为,以便路径模式secondapp/*指向SecondApp存储桶URL。

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

但是,如果我省略了尾部斜杠,我会看到第一个应用程序,这是不受欢迎的。如果我访问www.mywebsite.com/secondapp/something,我也会看到第一个应用程序,这也是不受欢迎的。 (我希望它加载secondapp的.html)

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

我希望的行为是访问以下内容显示正确的站点/存储桶:

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

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

www.mywebsite.com/secondapp - (没有尾随斜线)不工作,显示First App

www.mywebsite.com/secondapp/something_else - 不工作,显示First App

我怎样才能实现理想的行为?

谢谢!

amazon-web-services amazon-s3 single-page-application amazon-cloudfront create-react-app
1个回答
2
投票

在研究了这个问题后,我能够使用lambda @ edge(https://aws.amazon.com/lambda/edge/)解决它

通过部署一个简单的javascript函数将特定路径路由到所需的s3存储桶,我们能够实现类似nginx的路由设置。该函数位于我们的Cloudfront CDN上的lambda @ edge上,这意味着您可以指定何时触发它。对我们来说,它是在“原始请求”上

我的设置如下:

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

这是我使用的lambda函数的一个例子。


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);
};

这些是我用于此解决方案的资源:

© www.soinside.com 2019 - 2024. All rights reserved.