如何将 CloudFront 中的子域映射到 S3 中的同名?

如何将 CloudFront 中的子域映射到 S3 中的同名?

我一直在寻找以下方法,如果有人能启发我,我将不胜感激。

例如,在单个 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,可以直接返回承诺,或者可以如上所示编写以使用回调接口。

相关内容