我有一个 Cloudfront 发行版,其来源设置为 S3 存储桶。我添加了一个 Cloudfront 功能,以便只需键入文件夹名称即可访问文件夹“内”的索引文档,而不是“index.html”部分。 (我说“内部”是因为 S3 文件夹只是前缀,而不是实际的文件夹。)
这是 Cloudfront 功能:
function basename(str, sep) {
return str.substr(str.lastIndexOf(sep) + 1);
}
function handler(event) {
var request = event.request;
var uri = request.uri;
f = basename(request.uri, '/');
if (!f.includes('.')) {
if (request.uri.endsWith('/')) {
request.uri += 'index.html';
}
else {
request.uri += '/index.html';
}
}
return request;
}
在分发行为中,我将“查看者请求”设置为“CloudFront Functions”和“indexfcn”(我的函数名称)。 “查看者响应”、“源请求”和“源响应”设置为“无关联”。
该存储桶有一个名为“aup”的文件夹,其中包含文件“index.html”。还有一个名为“images”的子文件夹,其中包含“index.html”引用的图像。图像是相对于包含“index.html”的基本目录引用的,例如“images/AUPLogoHome.gif”。
发生的事情是这样的:
“https://x1xajt1fdtgq9p.cloudfront.net/aup/”(尾部斜杠)工作正常,带有图像的完整网页。 “https://d1xajt1fdtgq3p.cloudfront.net/aup/index.html”也是如此。
“https://x1xajt1fdtgq9p.cloudfront.net/aup”为我提供了正确的 HTML 渲染,但缺少所有图像。
“https://x1xajt1fdtgq9p.cloudfront.net/aup/images/AUPLogoHome.gif”显示图像。
知道发生了什么吗?
一个猜测是,当我访问“https://x1xajt1fdtgq9p.cloudfront.net/aup”时,Cloudfront或S3不知道基目录是什么。为了测试这个理论,我将这一行添加到“index.html”页面:
<base href="https://x1xajt1fdtgq9p.cloudfront.net/aup/">
现在“https://x1xajt1fdtgq9p.cloudfront.net/aup”可以工作了。
但是在文件中放置“base”标签是不切实际的。我需要一种方法来以某种方式从 Cloudfront 函数设置基础。当我使用尾随斜杠时,它显然已设置,但不是没有斜杠。
检查任何常见 Web 服务器(Nginx、Apache 等)对索引文档的行为,您会发现自己的疏忽:当浏览器请求
/aup
时,您需要返回 3xx 重定向,以便浏览器随后请求 /aup/
只有这样你才应该返回索引文档的内容。这就是传统网络服务器所做的。
图像的链接由浏览器相对于当前文档 URI 的目录进行解释,如您所知...但是您忽略的是在这两种不同情况下实际所在的目录。
与
cat.jpg
同目录下的文件/foo/bar/
是/foo/bar/cat.jpg
。
与
cat.jpg
位于同一目录中的文件 /foo/bar
是 /foo/cat.jpg
,因为 /foo/bar
被浏览器解释为 bar
目录中名为 /foo
的文件。这是浏览器得出的唯一合理的结论。缺少尾部斜杠完全改变了含义。
因此,您所看到的并不是奇怪的行为 - 这是浏览器方面的正确行为,与 S3 或 CloudFront 无关。浏览器必须了解基本目录。