![如何将 CloudFront 中的子域映射到 S3 中的同名?](https://linux22.com/image/726916/%E5%A6%82%E4%BD%95%E5%B0%86%20CloudFront%20%E4%B8%AD%E7%9A%84%E5%AD%90%E5%9F%9F%E6%98%A0%E5%B0%84%E5%88%B0%20S3%20%E4%B8%AD%E7%9A%84%E5%90%8C%E5%90%8D%EF%BC%9F.png)
我一直在寻找以下方法,如果有人能启发我,我将不胜感激。
例如,在单个 CloudFront 实例中是否可以进行以下映射?
feature-a.domain.com => dev-bucket/feature-a
feature-b.domain.com => dev-bucket/feature-b
staging.domain.com => dev-bucket/staging
等等。
用例是我希望能够为每个映射到 S3 上存在的存储桶的 git 分支部署尽可能多的环境。这一切都可能吗?
答案1
是的,这是可能的,但是您需要使用 CloudFront 的 Lambda@Edge 增强功能,以便在将请求发送到存储桶之前操作请求参数。
我描述了一个可能的解决方案这个官方论坛帖子。下面包含相同的解决方案。
Lambda@Edge 允许在 CloudFront 处理 HTTP 请求或响应时以编程方式访问它们 - 本质上提供触发器挂钩。HTTP 事务以 javascript 对象的形式呈现,您可以观察和修改它,然后将控制权返回给 CloudFront。
对于此应用程序,您需要使用存储桶的网站托管端点作为 CloudFront 配置中的原始域名(即,不要从下拉列表中选择存储桶 - 使用适当的“s3-website”主机名输入它)并且您需要将Host
标头列入白名单以转发到原点,即使我们实际上不会转发它(我们将读取它,然后操作它以及路径),即使通常将其转发到 S3 原点不会按预期工作...但我们需要告诉 CloudFront 将其列入白名单,以便可以读取和操作它。
将以下 Lambda 函数配置为源请求触发器。此触发器在检查 CloudFront 缓存并发生缓存未命中之后,以及在将请求发送到源服务器 (S3) 之前触发。
'use strict';
// https://serverfault.com/a/930191/153161
// 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)
// set this to what we should remove from the incoming hostname, including the leading dot.
const remove_suffix = '.example.com';
// provide the correct origin hostname here so that we send the correct
// Host header to the S3 website endpoint
// this is the same value as "origin domain name" in the cloudfront distribution configuration
const origin_hostname = 'example-bucket.s3-website-us-east-1.amazonaws.com';
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
// we have to do this even if the above if() didn't match
headers.host[0].value = origin_hostname;
// return control to CloudFront with the modified request
return callback(null,request);
};
请记住设置您的错误缓存最小 TTL 为 0以避免出现 CloudFront 缓存错误响应。这是与缓存行为设置中的最小/默认/最大 TTL 不同的设置。默认值为 5 分钟,这很有意义,但如果您没有预料到这种行为,则会使故障排除变得复杂。
请注意,Lambda@Edge 函数现在可以使用 v6.10 或8.10版Node.js 运行时环境。上面的示例最初是为 v6.10 编写的,但与任一运行时都兼容,因为在 v8.10 中,处理程序具有更多选项:它可以使用 async/await,可以直接返回承诺,或者可以如上所示编写以使用回调接口。