Amazon s3 未找到时指向回退S3域子文件夹的Lambda脚本
根据这一点,以及下面的一段代码,允许我将S3 bucket中的一个子文件夹指向我的域 但是,在未找到子域的情况下,我会收到以下错误消息:Amazon s3 未找到时指向回退S3域子文件夹的Lambda脚本,amazon-s3,Amazon S3,根据这一点,以及下面的一段代码,允许我将S3 bucket中的一个子文件夹指向我的域 但是,在未找到子域的情况下,我会收到以下错误消息: <Error> <Code>AccessDenied</Code> <Message>Access Denied</Message> <RequestId>2CE9B7837081C817</RequestId> <HostId> T3p7mzSYztPhXetUu
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>2CE9B7837081C817</RequestId>
<HostId>
T3p7mzSYztPhXetUu7GHPiCFN6l6mllZgry+qJWYs+GFOKMjScMmRNUpBQdeqtDcPMN3qSYU/Fk=
</HostId>
</Error>
我不希望它显示此错误消息,相反,在这种情况下,我希望从另一个S3 bucket子域(即example bucket.S3 website.us-east-2.amazonaws.com/error
)提供服务,例如,在那里,用户将收到一条奇特的错误消息。因此,在没有找到S3 bucket子文件夹的情况下,它应该返回到那里。如何通过更改下面的节点函数来实现这一点
'use strict';
// if the end of incoming Host header matches this string,
// strip this part and prepend the remaining characters onto the request path,
// along with a new leading slash (otherwise, the request will be handled
// with an unmodified path, at the root of the bucket)
const remove_suffix = '.example.com';
// provide the correct origin hostname here so that we send the correct
// Host header to the S3 website endpoint
const origin_hostname = 'example-bucket.s3-website.us-east-2.amazonaws.com'; // see comments, below
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const host_header = headers.host[0].value;
if(host_header.endsWith(remove_suffix))
{
// prepend '/' + the subdomain onto the existing request path ("uri")
request.uri = '/' + host_header.substring(0,host_header.length - remove_suffix.length) + request.uri;
}
// fix the host header so that S3 understands the request
headers.host[0].value = origin_hostname;
// return control to CloudFront with the modified request
return callback(null,request);
};
Lambda@Edge函数是一个源请求触发器——它在检查CloudFront缓存并发生缓存未命中后运行,紧接着在请求(被触发器代码修改后的状态)发送到源服务器之前运行。当响应从源站到达时,此代码已完成,无法用于修改响应 有几种解决方案,包括一些概念上有效但效率极低的解决方案。尽管如此,为了彻底起见,我还是要提到这些以及更清洁/更好的解决方案 Lambda@Edge有:
- 查看器请求-当请求第一次到达CloudFront时,在检查缓存之前;为每一个请求开火
- 原始请求-在确认请求为缓存未命中之后,但在将请求发送到原始服务器之前;仅在缓存中触发未命中
- 源响应-在从源服务器返回响应(无论是成功还是错误)之后,但在响应可能存储在缓存中并返回给查看器之前;如果此触发器修改响应,修改后的响应将存储在CloudFront缓存(如果可缓存)中,并返回给查看器;仅在缓存未命中时激发
- 查看器响应-在响应返回到查看器之前,无论是从源站还是缓存;为每个非错误响应激发,除非该响应是由查看器请求触发器自发发出的,或者是将状态代码设置为200(明确的反模式,但仍然可能)的自定义错误文档的结果,或者是CloudFront生成的HTTP到HTTPS重定向
- 创建指向桶的第二个CloudFront原点
- 创建一个新的缓存行为,将一条路径(例如,
)精确地路由到错误文件,再路由到新的源(这意味着您不能在任何子域上使用该路径——它总是在任何时候被请求时直接转到错误文件)/shared/errors/not found.html
- 为代码403配置CloudFront自定义错误响应,以使用路径
/shared/errors/not found.html
- 至少在测试时,将错误缓存最小TTL设置为0,以避免自己遇到一些挫折。请参阅但忽略我说过的“将
自定义错误响应设置为
”部分否
${bucket}.s3website.${region}.amazonaws.com
。在某些地区,由于传统原因,主机名可能在s3网站
之后有一个破折号-
而不是一个点
,但点格式应该适用于任何地区
我几乎不愿意提及脑海中出现的另一个选项,因为它相当先进,我担心描述可能会显得相当复杂。。。但是你也可以做下面的事情,这将是非常巧妙的,因为它将允许你为每个错误的URL请求生成一个定制的HTML页面 创建一个CloudFront,主bucket作为主bucket,第二个空的“占位符”bucket作为辅助bucket。第二个bucket的唯一用途是为CloudFront提供一个它计划连接到的有效名称,尽管我们实际上不会连接到它,下面可能会很清楚 当请求未能发送到主原点(与配置的错误状态代码之一匹配)时,将联系辅助原点。这是为了处理这个案件
event.Records[0].cf.request.origin.s3.domainName # S3 rest endpoints
event.Records[0].cf.request.origin.custom.domainName # non-S3 origins and S3 website-hosting endpoints