我做了类似的事情,以便能够将 cookie 转发到为粘性会话配置的 ALB,而无需使用 cookie 进行缓存。这样做的原因是因为 Cloudfront 在匹配请求和缓存的响应时将使用 cookie 及其值,但是因为 ALB 在每个响应上创建一个新的会话 cookie,所以请求永远不会匹配缓存,因为查看器总是有一个新的 cookie 值集。
我也将 cookie 移动到查看器请求中的自定义标头,然后将其从标头中拉出并放回原始请求中的 cookie 中。我对查看器请求和原始请求使用了相同的 lambda 函数,并检查了配置属性以确定它是哪个触发器。我更喜欢这种模式,这样我可以在读取/编写代码时遵循从查看器请求到源请求的逻辑,因为查看器请求的回调响应成为源请求的事件请求,我可以在单个函数上运行我的测试。该逻辑基于三个流程:
- 根本没有 AWSALB cookie 或客户标头 - 在这种情况下什么也不做
- 请求中有 AWSALB cookie 但没有其他 cookie
- 这是 AWSALB cookie 以及其他 cookie
使用这三个用例,该功能能够正常工作。
这是功能:
exports.handler = (event, context, callback) => {
// TODO implement
const util = require('util');
const COOKIE_TO_FORWARD = 'AWSALB';
let hasTheHeader = (request, headerKey) => {
if (request.headers[headerKey]) {
return true;
}
else return false;
}
//Returns the cookie key name from the value of the cookie header in the request
//let getCookieKey = cookieString => cookieString.slice(0,cookieString.indexOf("="));
const request = event.Records[0].cf.request
if(event.Records[0].cf.config.eventType == 'viewer-request') {
console.log('Viewer Request');
console.log(`viewer request – ${util.inspect(event, {showHidden: false, depth: null})}`);
hasTheHeader(event.Records[0].cf.request, 'cookie') ? console.log(`This request has cookies`) : console.log(`This request does NOT have cookies`);
// First check – If no cookies in Viewer Request, do nothing
if (!hasTheHeader(request, 'cookie')) {
console.log('viewer request first check evaluated - no cookies');
//pass request onto cloudfront cacheing layer or origin request
callback(null, request);
return;
}
// else there is a cookie header so get the list of cookies and put them in an array
let cookieList = request.headers.cookie[0].value.split('; ');
console.log(cookieList);
// Second check - If only the COOKIE_TO_FORWARD cookie exists and no other cookies, move it to a custom header and delete the cookie header
if ( (cookieList.length == 1) && (cookieList[0].startsWith(COOKIE_TO_FORWARD)) ) {
console.log('viewer request second check evaluated - only the COOKIE_TO_FORWARD cookie exists, no other cookies')
//move awsalb to custom header - format is important
request.headers.awsalbkey = [{'key': 'awsAlbKey', 'value': cookieList[0]}];
//remove cookie header
delete request.headers.cookie;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//pass request onto cloudfront cacheing layer or origin request
callback(null, request);
return;
}
// Third check - If there are multiple cookies including the COOKIE_TO_FORWARD cookie, move only the COOKIE_TO_FORWARD cookie to a custom header and delete the cookie COOKIE_TO_FORWARD cookie
// get awsAlb cookie
const indexOfAwsALbCookie = cookieList.findIndex(element => element.startsWith('AWSALB='));
if ( (cookieList.length > 1) && (indexOfAwsALbCookie > -1) ) {
console.log('viewer request third check evaluated - the COOKIE_TO_FORWARD cookie exists along with other cookies')
//put awsAlb cookie value to custom header - format is important
request.headers.awsalbkey = [{'key': 'awsAlbKey', 'value': cookieList[indexOfAwsALbCookie]}];
//remove awsAlb cookie from list off cookies in request
cookieList.splice(indexOfAwsALbCookie,1);
let cookieListString = cookieList.join('; ');
request.headers.cookie[0].value = cookieListString;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//pass request onto cloudfront cacheing layer or origin request
callback(null, request);
return;
}
}
else if(event.Records[0].cf.config.eventType == 'origin-request') {
console.log('Origin Request');
console.log(`origin request – ${util.inspect(event, {showHidden: false, depth: null})}`);
hasTheHeader(request, 'cookie') ? console.log(`This request has cookies`) : console.log(`This request does NOT have cookies`);
// First check – If no cookies in Viewer Request AND no awsalbkey header, do nothing as this is the first request to the origin
if (!hasTheHeader(request, 'cookie') && !hasTheHeader(request, 'awsalbkey')) {
console.log('origin request first check evaluated - no cookies and no awsalbkey header');
//send request to origin
callback(null, request);
return;
}
//Second check, if no cookie header AND COOKIE_TO_FORWARD customer header exists, then add the cookie header and cookie and remove the COOKIE_TO_FORWARD custom header
if (!hasTheHeader(request, 'cookie') && hasTheHeader(request, 'awsalbkey')) {
console.log('origin request second check evaluated - no cookies and has the awsalbkey header')
//add the cookie header and the cookie obtained from the custom header
request.headers.cookie = [];
var length = request.headers.cookie.push({'key': 'Cookie', 'value': request.headers.awsalbkey[0].value});
//remove the custom header
delete request.headers.awsalbkey;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//send request to origin
callback(null, request);
return;
}
//else cookie list exists
let cookieListOrigin = request.headers.cookie[0].value.split('; ');
console.log(cookieListOrigin);
// Third check - If there are multiple cookies excluding the COOKIE_TO_FORWARD cookie and there's an COOKIE_TO_FORWARD custom header, move the COOKIE_TO_FORWARD custom header to the list of cookies and remove the COOKIE_TO_FORWARD custom header
let originIndexAwsAlbCookie = cookieListOrigin.findIndex(element => element.startsWith(COOKIE_TO_FORWARD));
if ( (originIndexAwsAlbCookie < 0) && (cookieListOrigin.length > 0) && (request.headers.awsalbkey) ) {
console.log('origin request third check evaluated - cookies exist without the awsalb cookie and has the awsalbkey header')
//add the awsalb customer header value to a new cookie in the cookie array
var length = cookieListOrigin.push(request.headers.awsalbkey[0].value);
let cookieListOriginString = cookieListOrigin.join('; ');
request.headers.cookie[0].value = cookieListOriginString;
//remove the custom header
delete request.headers.awsalbkey;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//send request to origin
callback(null, request);
return;
}
}
callback(null, request);
};