AWS CloudFront-转发用户代理,但不对其进行缓存

时间:2018-10-24 08:55:54

标签: http amazon-cloudfront user-agent

我希望我的血统能够看到User-Agent标头,例如:Gecko/20100101 Firefox/62.0而不是Amazon CloudFront

在“行为”选项卡中,我可以将User-Agent标头列入白名单,以便正确地将其传递到源,但是现在CloudFront根据User-Agent缓存内容,这意味着用户从不同的浏览器访问CloudFront端点会强制CloudFront进行以下操作:去原点。

是否可以将CloudFront配置为将某些标头传递给源头,但不一定要针对它们进行缓存?

编辑: Accept-Language标头也有类似的问题。我想将其传递给原点,但是我不想针对它进行缓存。我正在缓存的资产与语言无关,但是不可缓存的内容取决于Accept-Language标头。

3 个答案:

答案 0 :(得分:2)

您可以使用分配给CloudFront发行版的Lambda @ Edge函数(https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html)。您将需要两个功能:

  1. Viewer-Request事件处理程序,它将读取User-Agent标头并将其复制到例如X-My-User-Agent。在来自客户端的请求到达您的Cloudfront分发之前,将调用Viewer-Request处理程序。
  2. 原始请求事件处理程序,它将读取X-My-User-Agent并替换User-Agent。当Cloudfront在其缓存中未找到请求的页面并将其发送到源时,将调用Origin-Request处理程序。

请注意,您不应将User-Agent添加到Cloudfront白名单中:

  

您可以将CloudFront配置为基于以下内容缓存对象:   日期和User-Agent标头,但我们不建议这样做。这些标题   有很多可能的值,根据它们的值进行缓存会   使CloudFront向您转发更多的请求   来源。

参考:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-headers-behavior

Viewer-Request处理程序的示例(Lambda @ Edge只能用NodeJS编写,参考号:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-lambda-function-configuration):

'use strict';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;
  const customUserAgentHeaderName = 'X-My-User-Agent';
  const userAgent = headers['user-agent'][0].value;


  headers[customUserAgentHeaderName.toLowerCase()] = [
    {
      key: customUserAgentHeaderName,
      value: userAgent
    }
  ];


  callback(null, request);
};

Origin-Request处理程序示例:

'use strict';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;
  const customUserAgentHeaderName = 'X-My-User-Agent';
  const realUserAgent = headers[customUserAgentHeaderName.toLowerCase()][0].value;

  headers['user-agent'] = [
    {
      key: 'User-Agent',
      value: realUserAgent
    }
  ];


  callback(null, request);
};

答案 1 :(得分:1)

这可能是一个简单的解决方案。如果您想要User-Agent作为唯一类型的URL示例,则像这样的/ tracking / a,/ tracking / b为此路径[tracking *]创建一个新分发,并将User-Agent列入白名单。因此,您不必为所有URL而是仅针对此路径使用AWS缓存。

答案 2 :(得分:0)

如果请求跨不同的用户代理缓存,则在命中的情况下,真实用户代理将完全不会传递到源。 CloudFront只会返回缓存的响应。

您提到您想将用户代理信息发送到Elasticsearch。除非您仅对丢失的请求感兴趣,否则您将不能依赖从原始应用程序收集的日志。

如果您有Lambda @ Edge以realUserAgent的形式发送用户代理,但用户代理标头本身不是缓存参数,则在{{1}的情况下,源仍不会接收该数据}。

我在这里看到的唯一解决方案是使用从CloudFront生成的访问日志。 CloudFront访问日志不仅包含用户代理,还包含IP地址和其他有用信息。该数据既记录了命中数据,也记录了未命中数据。设置日志记录将信息发送到Elasticsearch也很容易。