从CloudFront和S3中提供gzip和br文件

3
当客户端请求头包含 Accept-Encoding: gxip, deflate, br 时,S3 + Cloudfront 无法提供 .gz/.br 静态文件。
  1. 在构建时压缩文件,并将 s3 文件夹中的 index.html、index.html.gz 和 index.html.br 添加到其中。
  2. 在 Cloudfront 的白名单中添加 Accept encoding 头。
  3. 在 S3 的 CORS 配置中添加 Content-Length。
  4. 为 index.html.gz 添加 gzip 编码和 index.html.br 添加 br 编码,并将 Content-Type 设置为 text/html。
  5. 禁用 Cloudfront 的自动压缩功能。
但是,我无法从 S3 + Cloudfront 获取已压缩的文件。我能够直接访问 index.html.gz,但 Cloudfront + S3 无法自动提供该文件。我有什么遗漏吗?或者不能以这种方式提供服务吗?

1
不,你请求 index.html,Cloudfront 会请求 index.html,S3 将为您提供该文件,无论请求中的 accept-encoding 标头如何,都不能根据扩展名提供压缩文件,压缩文件仍然需要是 index.html,但 S3 包含元数据 content-encoding: gzip,因此浏览器可以理解它是 zip 格式,而不是通过文件扩展名来理解。 - James Dean
我该如何提供 Brotli 文件? - rinesh
1
与zip相同,有一个带有index.html的br压缩文件,设置content-encoding: br,以便浏览器可以理解它被压缩了。 - James Dean
1
是的,S3不像典型的服务器那样查看accept-encoding头并提供该文件,您需要实现逻辑,例如lambda@edge来完成该工作,只需记住CloudFront如果不是gzip,则会删除accept-encoding头,如果您计划编写origin request lambda@edge,则需要将其列入白名单。 - James Dean
2
嗨@rinesh,你找到解决方案了吗?你能够根据accept-encoding头同时提供brotli和gzip文件吗? - Always_a_learner
显示剩余2条评论
1个回答

2
这可以通过CloudFront -> Lambda@Edge (Origin request) -> S3来完成。 自此问题被提出后,AWS已经添加了Accept-Encoding头以传递给S3,因此Lambda函数可以使用它。
Lambda将获取接受编码头,检查其中是否包含brotli,如果是,则会向发送到S3存储桶的请求中添加所需的扩展名。 客户端仍然可以访问相同的URL,但根据接受编码头,将获得不同的结果。 此外,请确保您的CloudFront缓存策略基于接受编码头。 Lambda的示例代码:
'use strict';

/**
 * Funciton registered on 'Origin Request' CloudFront Event
 */
exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;
  var isBr = false;
  
  
  if(headers['accept-encoding'] && headers['accept-encoding'][0].value.indexOf('br') > -1) {
    isBr = true;
  }
  const gzipPath = '.gz';
  const brPath = '.br';

  /**
  * Update request path based on custom header
  */  
  request.uri = request.uri + (isBr ? brPath : gzipPath);
  callback(null, request);
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接