AWS CloudFront - 转发 User-Agent 但不对其进行缓存
AWS CloudFront - forward User-Agent but don't cache against it
我希望我的来源能够看到 User-Agent
header。例如:Gecko/20100101 Firefox/62.0
而不是 Amazon CloudFront
。
在“行为”选项卡中,我可以将 User-Agent
header 列入白名单,因此它可以正确传递到源,但是现在 CloudFront 缓存每个 User-Agent
的内容,这意味着访问 CloudFront 端点的用户来自不同浏览器的请求会强制 CloudFront 转到源。
是否有任何方法可以配置 CloudFront 将一些 header 传递给源,但不一定对它们进行缓存?
编辑:
Accept-Language
header 也有类似的问题。我想将它传递给原点,但我不想对其进行缓存。我正在缓存的资产不依赖于语言,但是 non-cachable 内容依赖于 Accept-Language
header.
您可以使用分配给您的 CloudFront 分配的 Lambda@Edge 函数 (https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html)。您将需要两个函数:
- Viewer-Request 事件处理程序,它将读取
User-Agent
header 并将其复制到例如X-My-User-Agent
。 Viewer-Request 在来自客户端的请求到达您的 Cloudfront 分发之前调用处理程序。
- Origin-Request 事件处理程序,它将读取
X-My-User-Agent
并替换 User-Agent
。 Origin-Request 当 Cloudfront 在其缓存中找不到请求的页面并将请求发送到源时,将调用处理程序。
请注意,您不应将 User-Agent
添加到 Cloudfront 白名单:
You can configure CloudFront to cache objects based on values in the
Date and User-Agent headers, but we don't recommend it. These headers
have a lot of possible values, and caching based on their values would
cause CloudFront to forward significantly more requests to your
origin.
Viewer-Request 处理程序示例(Lambda@Edge 只能用 NodeJS 或 Python 编写,参考: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);
};
如果请求缓存在不同的 user-agents 中,万一命中,real-user 代理根本不会传递到源。 CloudFront 只会 return 缓存的响应。
您提到您喜欢将 user-agent 信息发送到 Elasticsearch。除非您只对错过的请求感兴趣,否则您不能依赖从源应用程序收集的日志。
如果您让 Lambda@Edge 将 user-agent 作为 realUserAgent
发送,但 user-agent header 本身不是缓存参数,源端仍然不会收到Miss
.
情况下的数据
我在这里看到的唯一解决方案是使用从 CloudFront 生成的访问日志。 CloudFront 访问日志不仅包含 user-agent,还包含 IP 地址和其他有用信息。此数据会记录命中和未命中。设置 logstash 以将此信息发送到 Elasticsearch 也很容易。
这可能是一个简单的解决方案。如果您想要 User-Agent 用于独特类型的 URL 示例,/tracking/a、/tracking/b 会为此路径创建一个新分发 [tracking*] 并将 User-Agent 仅用于此分发。因此,您不会将 AWS 缓存用于所有 url,而只是用于此路径。
亚马逊似乎在 2020 年 7 月左右推出了新功能“Origin Request policies”。您应该能够使用它(不会陷入 Lambda@Edge 的困境):https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-cloudfront-announces-cache-and-origin-request-policies/
TLDR:
Over time, we’ve seen numerous cases in which the new functionality could be useful for customers. Examples such as:
- Forwarding information such as the User-Agent to the origin for analytics/logging but without serving different content variants based on device type (now you can forward the user-agent header and exclude it from the cache-key)
^ 这是您的用例:)
我希望我的来源能够看到 User-Agent
header。例如:Gecko/20100101 Firefox/62.0
而不是 Amazon CloudFront
。
在“行为”选项卡中,我可以将 User-Agent
header 列入白名单,因此它可以正确传递到源,但是现在 CloudFront 缓存每个 User-Agent
的内容,这意味着访问 CloudFront 端点的用户来自不同浏览器的请求会强制 CloudFront 转到源。
是否有任何方法可以配置 CloudFront 将一些 header 传递给源,但不一定对它们进行缓存?
编辑:
Accept-Language
header 也有类似的问题。我想将它传递给原点,但我不想对其进行缓存。我正在缓存的资产不依赖于语言,但是 non-cachable 内容依赖于 Accept-Language
header.
您可以使用分配给您的 CloudFront 分配的 Lambda@Edge 函数 (https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html)。您将需要两个函数:
- Viewer-Request 事件处理程序,它将读取
User-Agent
header 并将其复制到例如X-My-User-Agent
。 Viewer-Request 在来自客户端的请求到达您的 Cloudfront 分发之前调用处理程序。 - Origin-Request 事件处理程序,它将读取
X-My-User-Agent
并替换User-Agent
。 Origin-Request 当 Cloudfront 在其缓存中找不到请求的页面并将请求发送到源时,将调用处理程序。
请注意,您不应将 User-Agent
添加到 Cloudfront 白名单:
You can configure CloudFront to cache objects based on values in the Date and User-Agent headers, but we don't recommend it. These headers have a lot of possible values, and caching based on their values would cause CloudFront to forward significantly more requests to your origin.
Viewer-Request 处理程序示例(Lambda@Edge 只能用 NodeJS 或 Python 编写,参考: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);
};
如果请求缓存在不同的 user-agents 中,万一命中,real-user 代理根本不会传递到源。 CloudFront 只会 return 缓存的响应。
您提到您喜欢将 user-agent 信息发送到 Elasticsearch。除非您只对错过的请求感兴趣,否则您不能依赖从源应用程序收集的日志。
如果您让 Lambda@Edge 将 user-agent 作为 realUserAgent
发送,但 user-agent header 本身不是缓存参数,源端仍然不会收到Miss
.
我在这里看到的唯一解决方案是使用从 CloudFront 生成的访问日志。 CloudFront 访问日志不仅包含 user-agent,还包含 IP 地址和其他有用信息。此数据会记录命中和未命中。设置 logstash 以将此信息发送到 Elasticsearch 也很容易。
这可能是一个简单的解决方案。如果您想要 User-Agent 用于独特类型的 URL 示例,/tracking/a、/tracking/b 会为此路径创建一个新分发 [tracking*] 并将 User-Agent 仅用于此分发。因此,您不会将 AWS 缓存用于所有 url,而只是用于此路径。
亚马逊似乎在 2020 年 7 月左右推出了新功能“Origin Request policies”。您应该能够使用它(不会陷入 Lambda@Edge 的困境):https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-cloudfront-announces-cache-and-origin-request-policies/
TLDR:
Over time, we’ve seen numerous cases in which the new functionality could be useful for customers. Examples such as:
- Forwarding information such as the User-Agent to the origin for analytics/logging but without serving different content variants based on device type (now you can forward the user-agent header and exclude it from the cache-key)
^ 这是您的用例:)