从S3 cloudfront静态网站重定向中删除root /

时间:2018-04-09 22:48:31

标签: amazon-s3 amazon-cloudfront

我有一个静态S3网站,只指向不同的域:https://www.externaldomain.com/id12345

此S3将分配给CloudFront,然后将其分配给A记录到mydomain.com

结果是当我导航到mydomain.com时,它会将访问者重定向到https://www.externaldomain.com/id12345

一切正常,但最后使用 / 重定向到https://www.externaldomain.com/id12345/

如果没有 /

,如何将其重定向到https://www.externaldomain.com/id12345

我无法控制externaldomain.com,当包含 / 时,它会给出404。

2 个答案:

答案 0 :(得分:3)

当您选择将所有请求重定向到另一个主机的选项时,S3假定您要在新URL的末尾保留原始请求路径。请求URI始终以/开头,因此当S3将传入请求URI附加到您在生成重定向时提供的路径时,S3会在您的请求结尾处显示/。并不是说S3正在添加它,因为它是从传入的请求URI中复制

所以这种行为乍一看很混乱,但不是不正确。

您在评论中所说的是,无论路径如何,都要将其丢弃。所有请求都转到目标服务上的单个路径。

为此,请使用路由规则。选择"使用此存储桶来托管网站"然后为索引文档组成一个名称 - 您实际上并不需要这个用例,但该字段不是可选字段,因此只需输入index.html即可。然后,添加如下所示的重定向规则:

<RoutingRules>
  <RoutingRule>
    <Condition>
        <KeyPrefixEquals></KeyPrefixEquals> <!-- empty string matches all requests -->
     </Condition>
    <Redirect>
        <Protocol>https</Protocol>
        <HostName>other-site.example.com</HostName>
        <ReplaceKeyWith>12345</ReplaceKeyWith> <!-- new path, with *no* leading slash -->
    </Redirect>
  </RoutingRule>
</RoutingRules>  

有关路由规则语法的详细信息,请参阅“S3开发人员指南”中的Advanced Conditional Redirects

文档没有提及使用空<KeyPrefixEquals>来匹配所有请求,但这是有效的,因为您要求规则测试的是(伪代码)left(key,0) == '',当然总是如此。

同样不明确的是,按照惯例,S3对象密钥不以/开头(HTTP中使用的前导/在概念上是之前的对象键的第一个字符)。这就是<ReplaceKeyWith>和任何其他关键参考在重定向路由规则中不需要(并且不应该)领先/的原因。

最佳做法建议您忽略以下替代解决方案,以供您考虑。它在很多方面都是可怕的,黑客的和错误的,但它应该适用于许多应用......

使用&#34;重定向请求&#34;选项,就像您最初所做的那样,但将#放在您提供的路径的末尾。然后S3重定向到https://example.com/12345#/,或者更确切地说,https://example.com/12345#${original_uri}。因为#标记了URI片段的开头,所以它不会被发送到目标服务器,因此它也应该按照您想要的方式执行,尽管它可以与SPA路由器交互,如果这样做的话。你正在使用的是什么。

答案 1 :(得分:1)

上面接受的答案使用了不再受支持的 XML。这是使用 JSON 的答案,AWS 现在需要它。我试图编辑已接受的答案,但版主 rejected 我的编辑改变了原作者的意图。去图。

当您选择将所有请求重定向到另一台主机的选项时,S3 假定您希望在新 URL 的末尾保留原始请求路径。请求 URI 始终以 / 开头,因此当 S3 将传入的请求 URI 附加到您在生成重定向时提供的路径时,最后是您的请求中的 /。与其说是 S3 添加它,不如说是从传入的请求 URI 中复制它。

因此行为乍一看令人困惑,但并非错误。

你在评论里说你想做的是,不管走哪条路,扔掉。所有请求都转到目标服务上的单一路径。

为此,请使用路由规则。选择Use this bucket to host a web site,然后为索引文档命名——对于这个用例,你实际上并不需要一个名称,但该字段不是可选的,所以只需输入 index.html。然后,添加如下所示的重定向规则:

    [
        {
            "Condition": {
                "KeyPrefixEquals": ""
            },
            "Redirect": {
                "HostName": "www.externaldomain.com",
                "Protocol": "https",
                "ReplaceKeyWith": "id12345"
            }
        }
    ]

有关路由规则语法的更多信息,请参阅 S3 开发人员指南中的 Advanced Conditional Redirects

文档没有提到使用空的 KeyPrefixEquals 来匹配所有请求,但这是有效的,因为您要求测试的规则是 (pseudocode) left(key,0 ) == '',这当然总是正确的。

同样不明确的是,按照惯例,S3 对象键不以 / 开头(从概念上讲,HTTP 中使用的前导 / 位于对象键的第一个字符之前)。这就是为什么 ReplaceKeyWith 和任何其他键引用不需要(也不应该)重定向路由规则中的前导 /。

最佳实践建议您忽略以下供您考虑的替代解决方案。它在很多方面都很可怕、很笨拙,而且是错误的,但它应该适用于许多应用程序......

使用“重定向请求”选项,就像您最初所做的那样,但将 # 放在您提供的路径的末尾。然后 S3 重定向到 https://externaldomain.com/id12345#/,或者更准确地说,https://externaldomain.com/id12345#${original_uri}。因为 # 标记了 URI Fragment 的开始,它不会发送到目标服务器,所以它也应该做你想做的,尽管它可能与 SPA 路由器交互,如果这是你正在使用的。