[英]Redirect to index.html for S3 subfolder
我有一个域example.com
。 我有一个名为example.com
的 S3 存储桶设置,其中包含一个可用的index.html
文件。 现在我想创建两个名为old
和new
的子文件夹,每个子文件夹包含一个单独版本的单页应用程序。 请求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 托管端点并手动将其弹出。
对 Cloudfront 分发源使用静态源意味着对该分发的任何请求都将使用 S3 的根对象查找,并且您的 404 响应应该随着引用流过而消失。
这样做之后:
否则,您所做的更改不会立即生效。
所以我昨晚也遇到了这个问题。
问题如下:当配置为网站存储桶时,S3 是宽容的并且具有索引文档设置,设置为index.html
并且这在根目录中应用,即example.com
实际上被重定向到example.com/index.html
,它也会在子文件夹级别应用,因此example.com/new
或example.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 重定向文件可以更简单地完成此操作
创建一个名为 my-great-new-post 的普通文件(不用担心不会与同一存储桶中的文件夹发生名称冲突)
在那个文件中写一个元重定向代码(我粘贴了下面的代码)
将文件上传到根存储桶(my-great-new-post 文件夹所在的位置)
修改新文件的元数据并制作 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 的解决方案。
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”,您可以将函数的行为修改为适合您的方式。
Origin
并将OriginPath
留空(默认值: /
)您可以在此处找到有用的演练
问题:如果您的客户输入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.