Amazon web services 如何在Cloudfront上为静态托管网站的子目录设置默认根对象?
如何在Cloudfront上为静态托管网站上的子目录设置默认根对象?具体来说,每当用户要求Amazon web services 如何在Cloudfront上为静态托管网站的子目录设置默认根对象?,amazon-web-services,amazon-s3,amazon-cloudfront,Amazon Web Services,Amazon S3,Amazon Cloudfront,如何在Cloudfront上为静态托管网站上的子目录设置默认根对象?具体来说,每当用户要求www.example.com/subdir/index.html时,我都希望提供www.example.com/subdir。注意,这是为了交付一个保存在S3存储桶中的静态网站。此外,我想使用源访问标识将对S3存储桶的访问限制为仅Cloudfront 现在,我知道Cloudfront的工作方式与S3和amazon的工作方式不同: CloudFront默认根对象的行为不同于 AmazonS3索引文档的行为。
www.example.com/subdir/index.html
时,我都希望提供www.example.com/subdir
。注意,这是为了交付一个保存在S3存储桶中的静态网站。此外,我想使用源访问标识将对S3存储桶的访问限制为仅Cloudfront
现在,我知道Cloudfront的工作方式与S3和amazon的工作方式不同:
CloudFront默认根对象的行为不同于
AmazonS3索引文档的行为。配置AmazonS3时
bucket作为网站并指定索引文档,AmazonS3返回
索引文档,即使用户请求
水桶(索引文件的副本必须出现在每个
有关配置AmazonS3的详细信息,请参阅
Bucket作为网站和关于索引文档,请参阅托管
亚马逊S3上的网站亚马逊简单存储服务章节
开发者指南
因此,尽管Cloudfront允许我们指定默认的根对象,但这只适用于www.example.com
,而不适用于www.example.com/subdir
。为了避免这个困难,我们可以将源域名更改为指向S3给定的网站端点。这非常有效,并允许统一指定根对象。不幸的是,这似乎不适合。具体而言,上述链接说明:
更改为编辑模式:
Web分发—单击“源”选项卡,单击要编辑的源,然后单击“编辑”。只能创建原点访问
原点类型为S3原点的原点标识
基本上,为了设置正确的默认根对象,我们使用S3网站端点,而不是网站bucket本身。这与使用源访问标识不兼容。因此,我的问题归结为两个方面
更新:看来我错了!请参阅JBaczuk的答案,这应该是该线程上可接受的答案。 不幸的是,你两个问题的答案都是否定的 1。是否可以为Cloudfront上静态托管网站的所有子目录指定默认根对象? 不,如……中所述 。。。如果定义了默认的根对象,则最终用户对发行版子目录的请求不会返回默认的根对象。例如,假设
index.html
是默认的根对象,并且CloudFront接收到最终用户对CloudFront发行版下的安装目录的请求:
即使安装目录中出现index.html
的副本,CloudFront也不会返回默认的根对象
CloudFront默认根对象的行为不同于AmazonS3索引文档的行为。将AmazonS3存储桶配置为网站并指定索引文档时,即使用户请求存储桶中的子目录,AmazonS3也会返回索引文档。(索引文档的副本必须出现在每个子目录中。)
2。如果源站是S3网站端点而不是S3存储桶,是否可以为Cloudfront提供的内容设置源站访问标识?
不直接。您可以选择使用CloudFront的源服务器是S3存储桶或您自己的服务器
不过,第二种选择确实带来了一些有趣的可能性。这可能会破坏您尝试执行的目的,但您可以设置自己的服务器,其唯一任务是作为CloudFront源服务器
当收到请求时,CloudFront会将此请求转发到您的源服务器,请求/install
。您可以根据需要配置源服务器,包括在本例中提供index.html
或者你也可以编写一个小的web应用程序,直接从S3获取这个调用
但是我意识到,设置自己的服务器并担心它的扩展可能会破坏您最初尝试的目的。有一种方法可以做到这一点。不要通过在下拉列表中选择它(www.example.com.s3.amazonaws.com)将其指向您的bucket的静态域(例如www.example.com.s3-website-us-west-2.amazonaws.com),而是将其指向您的bucket的静态域:
多亏了还有一种方法可以获得子目录中提供的默认文件,如
example.com/subdir/
。实际上,您可以(通过编程)在bucket中使用键subdir/
存储文件。这个文件不会出现在S3管理控制台中,但它确实存在,CloudFront将提供它。我知道这是一个老问题,但我只是自己解决了这个问题。最终,我的目标不是在目录中设置一个默认文件,而是在文件末尾提供一个没有.html
的文件的最终结果
我最终从文件名中删除了
.html
,并通过编程/手动将mime类型设置为text/html
。这不是传统的方式,但它似乎确实有效,并且在不牺牲cloudformation的好处的情况下满足了我对漂亮URL的要求。设置mime类型很烦人,但在我看来,为获得好处而付出的代价很小解决这个问题的方法是
'use strict';
/**
* Redirects URLs to default document. Examples:
*
* /blog -> /blog/index.html
* /blog/july/ -> /blog/july/index.html
* /blog/header.png -> /blog/header.png
*
*/
let defaultDocument = 'index.html';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
if(request.uri != "/") {
let paths = request.uri.split('/');
let lastPath = paths[paths.length - 1];
let isFile = lastPath.split('.').length > 1;
if(!isFile) {
if(lastPath != "") {
request.uri += "/";
}
request.uri += defaultDocument;
}
console.log(request.uri);
}
callback(null, request);
};
'use strict';
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda@Edge
var request = event.Records[0].cf.request;
// Extract the URI from the request
var olduri = request.uri;
// Match any '/' that occurs at the end of a URI. Replace it with a default index
var newuri = olduri.replace(/\/$/, '\/index.html');
// Log the URI as received by CloudFront and the new URI to be used to fetch from origin
console.log("Old URI: " + olduri);
console.log("New URI: " + newuri);
// Replace the received URI with the URI that includes the index page
request.uri = newuri;
// Return to CloudFront
return callback(null, request);
};
if ((window.location.href.endsWith("/") && !window.location.href.endsWith(".com/"))) {
window.location.href = window.location.href + "index.html";
}
else {
document.write("<Your 403 error message here>");
}
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)
aws s3api copy-object --copy-source bucket_name/subdir/index.html --key subdir/ --bucket bucket_name