繁体   English   中英

重定向到 S3 子文件夹的 index.html

[英]Redirect to index.html for S3 subfolder

我有一个域example.com 我有一个名为example.com的 S3 存储桶设置,其中包含一个可用的index.html文件。 现在我想创建两个名为oldnew的子文件夹,每个子文件夹包含一个单独版本的单页应用程序。 请求https://example.com/old (我喜欢在浏览器的地址栏中输入请求时省略index.html )将打开old子文件夹中的index.html文件并请求https://example.com/new将打开index.html 执行这些重定向的最佳方法是什么? 我应该在 Route 53 example.com/old -> example.com/old/index.html中设置一些东西还是有更好的方法?

不需要 lambda 函数来增加项目的费用和复杂性。

以下答案引用自https://stevepapa.com/

https://stevepapa.com/my-great-new-post/预计将以与以下方式相同的方式工作: https://stevepapa.com/my-great-new-post/index.html

有一个聪明的小方法可以让这些流向 Cloudfront 分发,它涉及更改 Cloudfront 默认显示给您的来源。

选择原始来源时,Cloudfront 将向您显示 S3 存储桶列表。 编辑原点

您无需从下拉列表中显示的存储桶中设置源,而是需要从其 S3 设置页面中获取该资源的静态 Web 托管端点并手动将其弹出。 静态托管端点 url 在哪里

对 Cloudfront 分发源使用静态源意味着对该分发的任何请求都将使用 S3 的根对象查找,并且您的 404 响应应该随着引用流过而消失。

重要的

这样做之后:

否则,您所做的更改不会立即生效。

所以我昨晚也遇到了这个问题。

问题如下:当配置为网站存储桶时,S3 是宽容的并且具有索引文档设置,设置为index.html并且这在根目录中应用,即example.com实际上被重定向到example.com/index.html ,它也会在子文件夹级别应用,因此example.com/newexample.com/new/都应该重定向到example.com/new/index.html ,存储桶中会有一个对象。 (否则,您会收到NoSuchKey错误。)

然而,您随后将自己“升级”到 CloudFront,可能是为了 HTTPS,并且此功能消失了。 CloudFront 改为对 S3 进行显式 API 调用,因此不会触发索引文档让步。 它确实适用于根目录,但不适用于子文件夹。

RoutingRules解决方案在我看来并不干净,因为通过指定KeyPrefixEquals而不是 key exactly equals(不存在)我认为你会得到意想不到的匹配。

相反,我实施了一个 Lambda@Edge 规则,该规则重写 CloudFront 向 S3 发出的请求以在其中具有适当的键值。

从此处的 Lambda 文档和 A/B 测试示例开始: https ://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html#lambda-examples-general-examples

将代码更改为:

'use strict';

exports.handler = (event, context, callback) => {
    /*
     * Expand S3 request to have index.html if it ends in /
     */
    const request = event.Records[0].cf.request;
    if ((request.uri !== "/") /* Not the root object, which redirects properly */
        && (request.uri.endsWith("/") /* Folder with slash */
            || (request.uri.lastIndexOf(".") < request.uri.lastIndexOf("/")) /* Most likely a folder, it has no extension (heuristic) */
            )) {
        if (request.uri.endsWith("/"))
            request.uri = request.uri.concat("index.html");
        else
            request.uri = request.uri.concat("/index.html");
    }
    callback(null, request);
};

并将其发布到您的 CloudFront 发行版。

使用 HTML 重定向文件可以更简单地完成此操作

  1. 创建一个名为 my-great-new-post 的普通文件(不用担心不会与同一存储桶中的文件夹发生名称冲突)

  2. 在那个文件中写一个元重定向代码(我粘贴了下面的代码)

  3. 将文件上传到根存储桶(my-great-new-post 文件夹所在的位置)

  4. 修改新文件的元数据并制作 Content-Type:text/html

这是文件的内容:

 <;DOCTYPE html> <html> <head> <meta http-equiv="refresh" content="0. url=/my-great-new-post/index.html"> </head> <body> </body> </html>

如果您使用的是 CloudFront,则可以使用CloudFront 函数来创建简单的重定向。

我修改了@jkingok 的解决方案。

  1. 转到 CloudFront,然后单击 Functions。
  2. 单击创建函数,输入名称和可选描述
  3. 在开发部分,输入下面的代码片段并从发布选项卡发布。
    function handler(event) {
      var request = event.request;
      if (request.uri !== "/" && (request.uri.endsWith("/") || request.uri.lastIndexOf(".") < request.uri.lastIndexOf("/"))) {
      if (request.uri.endsWith("/")) {
         request.uri = request.uri.concat("index.html");
      } else {
         request.uri = request.uri.concat("/index.html");
      }
     }
      return request;
   }

函数完成后,您可以通过转到分配的“行为”选项卡来使用该函数,选择要修改的路径模式,然后在“函数关联”下,对于查看器请求,选择“CloudFront 函数”作为函数类型,然后在下拉列表中选择您创建的函数。

函数关联截图

保存行为后,您可以测试您的网站。

注意:此解决方案将不带扩展名的每个 URL 重定向到“URL/index.html”,您可以将函数的行为修改为适合您的方式。

当您使用 S3 启用和配置静态托管时,您需要通过存储桶网站端点访问该站点。 您可以在静态网站托管部分的存储桶属性中找到此 URL。

S3 静态网站托管设置

网站端点的 URL 将如下所示:

http://example-bucket.s3-website-eu-west-1.amazonaws.com/example-folder/

然而(令人困惑的)存储在 S3 中的对象也可以通过不同的 URL 访问,这个 URL 不遵守子文件夹的索引规则。 这个 URL 看起来像这样:

https://example-bucket.s3-eu-west-1.amazonaws.com/example-folder/
  1. 配置您的 Bucket 以提供静态网站
  2. 创建CloudFront 分配:将您的存储桶设置为Origin并将OriginPath留空(默认值: /
  3. 创建链接到您的CloudFront 分配Route53 RecordSet

您可以在此处找到有用的演练

问题:如果您的客户输入example.com (没有old / new )会发生什么?

编辑: 2.是可选的。 您还可以将您的 Route53 RecordSet 链接到您的静态网站,但CloudFront 使您能够使用https (借助AWS Certificate Manager )为您的网站提供服务。

如果您使用 CDK 创建带有 S3 源的 CloudFrontWebDistribution,那么您的第一个猜测可能是这样做:

                OriginConfigs = new[] {
                    new SourceConfiguration {
                        S3OriginSource = new S3OriginConfig
                        {
                            S3BucketSource = bucket
                        }
                        Behaviors = new[] { new Behavior { IsDefaultBehavior = true } }
                    }
                }

但是,要将 cloudfront 配置为使用 website-bucket-url(确实具有将目录解析为 index.html 的行为),您需要使用:

                OriginConfigs = new[] {
                    new SourceConfiguration {
                        CustomOriginSource = new CustomOriginConfig
                        {
                            DomainName = bucket.BucketWebsiteDomainName,
                            OriginProtocolPolicy = OriginProtocolPolicy.HTTP_ONLY
                        },
                        Behaviors = new[] { new Behavior { IsDefaultBehavior = true } }
                    }
                }

您需要将协议指定为 HTTP_ONLY,因为网站存储桶不支持 HTTPS。 CustomOriginSource 的默认值为 HTTPS_ONLY。

您可以尝试设置重定向规则,这是一个未经测试的规则。

<RoutingRules>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>old</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>old/index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>new</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>new/index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM