如何在 S3/Cloudfront 的子文件夹中提供 index.html?

How do I serve index.html in subfolders with S3/Cloudfront?

得到一个名为 www.foo.site 的桶。在该站点中,有一个登录页面、一个关于页面和几个 bar/* 文件夹中的一些页面。每个 bar/* 都有一个 index.html 页:bar/a/index.html、bar/b/index.html 等

着陆页 运行 正常(这意味着 www.foo.site 将在我浏览时加载)但 /about/index.html 页面和 /bar/index.html 页面未提供服务当我点击我的关于链接等时。如果我 curl 我得到 404 的 URL。我尝试分别设置原始路径和原始域名:

第一次尝试:

domain name: www.foo.site.s3.amazonaws.com
origin path: (blank)

第二次尝试:

domain name: s3-us-west-1.amazonaws.com
origin path: www.foo.site

两者的默认文档都是 index.html。

都没有成功。 上面提到的所有 S3 页面都可以直接浏览。 意思是 https://s3-us-west-1.amazonaws.com/www.foo.site/bar/index.html 加载了预期的 html。

这一定是我缺少的某些 Cloudfront 设置。可能是我的 DNS 记录中的内容?是否可以通过 Cloudfront 在 S3 "folders" 中提供 html 文件?

这里有一些资源,在通过 https://domain/folder/ 从 S3 隐式提供 index.html 而不是必须显式使用 https://domain/folder/index.html:

时很有用

配置 CloudFront 分配时的关键是:

do not configure a default root object for your CloudFront distribution

如果您将 index.html 配置为默认根对象,则 https://domain/ 将正确提供 https://domain/index.html 但没有子文件夹引用(例如 https://domain/folder/ 将起作用。

在将 CF 分发连接到 S3 存储桶时,不要使用 Cloudfront 中的下拉菜单也很重要。您需要为 S3 静态站点使用 URL。

CloudFront 提供以 /

结尾的密钥的 S3 文件

经过调查,似乎可以在 S3 中以编程方式创建此类文件。因此,我写了一个在 S3 上创建文件时触发的小 lambda,后缀为 index.html 或 index.htm

它所做的是将对象dir/subdir/index.html复制到对象dir/subdir/

import json
import boto3

s3_client = boto3.client("s3")

def lambda_handler(event, context):

    for f in event['Records']:

        bucket_name = f['s3']['bucket']['name']
        key_name = f['s3']['object']['key']
        source_object = {'Bucket': bucket_name, 'Key': key_name}

        file_key_name = False

        if key_name[-10:].lower() == "index.html" and key_name.lower() != "index.html":
            file_key_name = key_name[0:-10]
        elif key_name[-9:].lower() == "index.htm" and key_name.lower() != "index.htm":
            file_key_name = key_name[0:-9]
        
        if file_key_name:
            s3_client.copy_object(CopySource=source_object, Bucket=bucket_name, Key=file_key_name)