amazon-cloudfront - 使用 AWS Lambda@Edge 设置带有用户位置的浏览器 cookie
问题描述
我有一个从 Cloudfront 加载的 HTML 内容。Cloudfrontcloudfront-viewer-country
在他的一些 Lambda@Edge 函数中添加带有用户国家/地区的标头 ( )。我尝试将用户的国家/地区发送到浏览器并使用 JS 代码读取它。
当我添加代码时
response.headers['cloudfront-viewer-country'] = request.headers["cloudfront-viewer-country"];
对于函数origin_reponse,来自 Cloudfront 的响应包含cloudfront-viewer-country
带有用户国家/地区的标头,但页面上的 JS 代码无法访问此数据。
我还尝试使用 cookie 将国家/地区发送到浏览器:
let finalCookieArray = [];
const cookiePath = '/';
finalCookieArray.push('cloudfront-viewer-country1='+ countryCode +'; SameSite=Strict; Path=' + cookiePath + '}');
response['headers']['set-cookie'] = [{
'key': 'Set-Cookie',
'value': finalCookieArray
}];
但是这个方法的问题是 Set-Cookie 不能从函数 origin_reponse 中工作。
最后我尝试在函数viewer_reponse中使用上面的代码,但是发送到 this 函数的请求不包含 header cloudfront-viewer-country
。
有什么方法可以通过 JS 代码(最好只使用 1 个 Lambda@Edge 函数)将 cloudfront 添加的国家发送到浏览器?
解决方案
经过一番调查,事实证明OriginResponse Lambda@Edge 函数能够添加将在浏览器中接收的 cookie。
要启用此类行为,必须定义 CloudFront 的分配Forward Cookies = Whitelist / All(取决于您的需要),如果使用白名单,请添加自定义 cookie 名称(我使用的 cookie 从未在我的会话中存在,这将阻止缓存通过 cookie 值并提高缓存的性能)。
就我而言,我想使用用户所在国家/地区的值设置一个 cookie(由 CloudFront 作为名为 的标头提供cloudfront-viewer-country
)。此标头仅在分发的设置设置为基于选定请求标头的缓存=白名单/全部(取决于您的需要)并且如果使用白名单添加标头cloudfront-viewer-country 时可用(如下图所示)
最后,一旦一切准备就绪,使用以下代码创建 Lambda@Edge 函数:
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda@Edge
var request = event.Records[0].cf.request;
var response = event.Records[0].cf.response;
if (!request)
{
callback(null, response);
return;
}
var countryCode = "Unknown";
// Get the user's country from CloudFront's header
const headers = request.headers;
if (!!headers &&
!!headers["cloudfront-viewer-country"] &&
0 < headers["cloudfront-viewer-country"].length &&
!!headers["cloudfront-viewer-country"][0].value)
countryCode = headers["cloudfront-viewer-country"][0].value;
if (!!response)
{
let finalCookieArray = [];
// Save previous set-cookies definitions
if(!!response['headers'] && !!response['headers']['set-cookie']){
for(var cookie of response['headers']['set-cookie']){
finalCookieArray.push(cookie.value);
}
}
// Add the country's value as a cookie
const cookiePath = '/';
finalCookieArray.push('user_country='+ countryCode +'; SameSite=Strict; Path=' + cookiePath);
response['headers']['set-cookie'] = [{
'key': 'Set-Cookie',
'value': finalCookieArray
}];
}
// Return to CloudFront
callback(null, response);
};
并将函数附加到分布
旁注:由于上述设置将为分发中的所有文件调用 Lambda 函数并可能损害缓存命中,因此您应考虑使用上述设置创建一个新行为(在 CloudFront 的分发中)并将路径模式设置为您要返回该国家/地区的 cookie 的相关文件。
推荐阅读
- r - 根据R中的列名组合多个数据集。列是统一的名称,但不是统一的数量
- c# - 选项卡中的复合模板错误中的文档
- amazon-web-services - 以 EC2 作为后端的 WebSocket API 实现
- python - 如何让 python unittest 仅在失败的测试中显示日志消息
- gradle - 从普通的战争包装中排除 spring boot devtools (developmentOnly) 依赖项
- apache - 如何在请求 uri 上添加路径
- python-3.x - 在 python 金字塔 web 框架中,如何在播种之前删除所有 db 表行?
- javascript - 每秒更改一次数字,但单击按钮后也会使数字下降
- python - 在没有 browsermodproxy 的情况下保存 HAR 文件
- javascript - React JS - 选择,为什么我要打印并存储在数据库中的双值