如何在 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
:
时很有用
- Serving index pages from a non-root location via CloudFront
- Serving index pages from a non-root location via CloudFront (now unavailable)
- Implementing Default Indexes in CloudFront Origins Using Lambda@Edge
配置 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)
得到一个名为 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
:
- Serving index pages from a non-root location via CloudFront
- Serving index pages from a non-root location via CloudFront (now unavailable)
- Implementing Default Indexes in CloudFront Origins Using Lambda@Edge
配置 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)