A/B deployment using Lambda@Edge trigger in Viewer request for two CloudFront Distributions (PLEASE HELP)

0

I'm trying to create an A/B deployment following an outdated guide and am having some issues trying to recreate it for my use case. This is the model I am trying to duplicate. Enter image description here

I've created 3 lamdba functions to recreate it. One for Viewer request, Origin Request, and Origin Response. I'll post them in a moment. The issue I'm having is that my created CF Distros using s3 buckets doesn't use OAI, so I'm not sure how to reference the two origins with the code. I appreciate all of your time and resources!

Enter image description here

Enter image description here

**VIEWER REQUEST **

'use strict';

const sourceCoookie = 'X-Source';
const sourceMain = 'abc1.s3-website-us-east-1.amazonaws.com';
const sourceExperiment = 'abc2.s3-website-us-east-1.amazonaws.com';
const experimentTraffic = 0.5;

// Viewer request handler
exports.handler =  (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    // Look for source cookie
    if ( headers.cookie ) {
        for (let i = 0; i < headers.cookie.length; i++) {        
            if (headers.cookie[i].value.indexOf(sourceCoookie) >= 0) {
                console.log('Source cookie found. Forwarding request as-is');
                // Forward request as-is
                callback(null, request);
                return;
            }         
        }       
    }

    console.log('Source cookie has not been found. Throwing dice...');
    const source = ( Math.random() < experimentTraffic ) ? sourceExperiment : sourceMain;
    console.log(`Source: ${source}`)

    // Add Source cookie
    const cookie = `${sourceCoookie}=${source}`
    console.log(`Adding cookie header: ${cookie}`);
    headers.cookie = headers.cookie || [];
    headers.cookie.push({ key:'Cookie', value: cookie });

    // Forwarding request
    callback(null, request);
};

**ORIGIN REQUEST **

'use strict';

const sourceCoookie = 'X-Source';
const sourceMain = 'abc1.s3-website-us-east-1.amazonaws.com';
const sourceExperiment = 'abc2.s3-website-us-east-1.amazonaws.com';
const experimentBucketName = 'abc2.s3-website-us-east-1.amazonaws.com';
const experimentBucketRegion = 'us-east-1';

// Origin Request handler
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    const source = decideSource(headers);

    // If Source is Experiment, change Origin and Host header
    if ( source === sourceExperiment ) {
        console.log('Setting Origin to experiment bucket');
        // Specify Origin
        request.origin = {
            s3: {
                authMethod: 'origin-access-identity',
                domainName: experimentBucketName,
                path: '',
                region: experimentBucketRegion    
            }
        };

        // Also set Host header to prevent “The request signature we calculated does not match the signature you provided” error
        headers['host'] = [{key: 'host', value: experimentBucketName }];
    }
    // No need to change anything if Source was Main or undefined
    
    callback(null, request);
};

**ORIGIN RESPONSE **

'use strict';

const sourceCoookie = 'X-Source';
const sourceMain = 'abc.s3-website-us-east-1.amazonaws.com';
const sourceExperiment = 'abc2.s3-website-us-east-1.amazonaws.com';
const cookiePath = '/';

// Origin Response handler
exports.handler =  (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const requestHeaders = request.headers;
    const response = event.Records[0].cf.response;    

    const sourceMainCookie = `${sourceCoookie}=${sourceMain}`;
    const sourceExperimenCookie = `${sourceCoookie}=${sourceExperiment}`;    

    // Look for Source cookie
    // A single cookie header entry may contains multiple cookies, so it looks for a partial match
    if (requestHeaders.cookie) {
        for (let i = 0; i < requestHeaders.cookie.length; i++) {    
            // ...ugly but simple enough for now   
            if (requestHeaders.cookie[i].value.indexOf(sourceExperimenCookie) >= 0) {
                console.log('Experiment Source cookie found');
                setCookie(response, sourceExperimenCookie);
                callback(null, response);
                return;
            }
            if (requestHeaders.cookie[i].value.indexOf(sourceMainCookie) >= 0) {
                console.log('Main Source cookie found');
                setCookie(response, sourceMainCookie);
                callback(null, response);
                return;
            }            
        }
    }
    
    // If request contains no Source cookie, do nothing and forward the response as-is
    console.log('No Source cookie found');
    callback(null, response);
}

// Add set-cookie header (including path)
const setCookie = function(response, cookie) {
    const cookieValue = `${cookie}; Path=${cookiePath}`;
    console.log(`Setting cookie ${cookieValue}`);
    response.headers['set-cookie'] = [{ key: "Set-Cookie", value: cookieValue }];    
}
1 Answer
0

Hi

You should set the authMethod to none since you are not using OAI.

As per Documentation

authMethod (read/write) (Amazon S3 origins only)
If you're using an origin access identity (OAI), set this field to origin-access-identity. If you aren't using an OAI, set it to none.
profile picture
EXPERT
answered a year ago
  • Thanks, I actually caught that and changed it. It still isn't working the way I wanted though. What else could be the issue?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions