来自 AWS CloudFront 且来源为 S3 的文件没有缓存控制标头

来自 AWS CloudFront 且来源为 S3 的文件没有缓存控制标头

我们刚刚迁移到 Amazon AWS。我们目前有一个运行良好的 EC2 实例。它在前端运行 Nginx,在后端运行 Apache。它也运行良好。所有网站都已正确启动,并包含从 EC2 提供的文件的 Cache-Control 标头。

问题出在我们放置的所有静态文件中亚马逊 S3正在通过CloudFront CDN我们可以正常访问文件(并且 CORS 也没有问题),但显然CloudFront 不提供带有 Cache-Control 标头的文件。我们希望利用浏览器缓存。

在我看来,EC2 实例在这里不起作用,因为静态文件由 S3 + CloudFront 直接提供,请求不会发送到 EC2 中的 Web 服务器。

我彻底迷失了。

问题:1) 在这种情况下,如何设置 Cache-Control?2) 是否可以设置 Cache-Control?从 S3 还是 CloudFront?

注意:我在 Google 上找到了几个页面,您可以在其中为单个对象设置 S3 中的标头。这确实不是一种有效的方法,特别是因为在我的例子中我们讨论的是多个对象。

谢谢!

答案1

我在 Google 上找到了几个页面,您可以在其中为单个对象设置 S3 中的标头。这确实不是一种有效的方法,特别是因为在我的例子中我们讨论的是多个对象。

好吧,无论是否“高效”,它实际上就是这么设计的。

CloudFront 没有添加 Cache-Control:标头。

CloudFront经过 (并且尊重,除非另有配置)Cache-Control:原始服务器提供的标头,在本例中为 S3 。

若要获取Cache-Control:S3 在获取对象时提供的标头,必须在将对象上传到 S3 时提供这些标头,或者通过后续的 put+copy 操作将其添加到对象的元数据中,该操作可用于在 S3 中将对象内部复制到自身,从而修改此过程中的元数据。如果您编辑对象元数据,控制台将在后台执行此操作。

而且(如果您想知道的话)S3 中也没有全局设置来强制存储桶中的所有对象返回这些标头 - 它是每个对象的属性。


更新: Lambda@Edge 是 CloudFront 的一项新功能它允许您在查看器和缓存之间和/或缓存和原点之间针对请求和/或响应触发触发器,并针对 CloudFront 公开的简单请求/响应对象结构运行用 Node.js 编写的代码。

此功能的主要应用之一是操作标题...因此,虽然上述内容仍然准确 - CloudFront 本身不会添加Cache-Control- 但现在 Lambda 函数可以将它们添加到从 CloudFront 返回的响应中。

此示例仅当响应中Cache-Control: public, max-age=86400没有标头时才会添加。Cache-Control

在 Origin Response 触发器中使用此代码会导致它在每次 CloudFront 从源获取对象时触发,并在 CloudFront 缓存之前修改响应。

'use strict';

exports.handler = (event, context, callback) => {
    const response = event.Records[0].cf.response;

    if(!response.headers['cache-control'])
    {
        response.headers['cache-control'] = [{ 
            key:   'Cache-Control', 
            value: 'public, max-age=86400' 
        }];
    }

    callback(null, response);
};

更新(2018-06-20):最近,我向 CloudFront 团队提交了一个功能请求,以允许配置静态来源回复标头作为来源属性,类似于静态要求现在可以添加标题...但有一个转折,允许将每个标题配置为有条件地添加(仅当原点未在响应中提供该标题时)或无条件地添加(添加标题并从原点覆盖标题,如果存在)。

对于功能请求,您通常不会收到任何确认,不知道他们是否真的在考虑实施新功能……或者他们是否已经在开发它……他们只是在完成后才宣布。所以,我不知道这些是否会实现。有一种观点认为,由于此功能已经通过 Lambda@Edge 提供,因此在基本功能中不需要它……但我的反驳是,如果没有执行简单、静态响应头操作的能力,那么基本功能在功能上就不完整,如果这是需要触发器的唯一原因,那么要求 Lambda 触发器是一种不必要的成本,无论是财务上还是增加延迟(尽管这两者都不一定是高昂的成本)。

答案2

自从2021 年 11 月,现在可以在 Cloudfront 中本地完成此操作,而无需使用 Lambda@Edge 函数。

  1. 转到 Cloudfront > 策略 > 响应标头,然后单击“创建响应标头策略”
  2. 输入名称,例如“CacheHeaders”,并添加自定义标头,如: 在此处输入图片描述
  3. 创建策略后,编辑分发的行为并选择 Resposne 标头策略部分下的策略: 在此处输入图片描述

相关内容