-
Notifications
You must be signed in to change notification settings - Fork 7
/
originRequest.js
120 lines (101 loc) · 4.13 KB
/
originRequest.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
'use strict';
const sourceCoookie = 'X-Source';
const sourceMain = 'main';
const sourceExperiment = 'experiment';
const experimentTraffic = 0.5;
const experimentBucketRegion = 'eu-west-1';
// S3 Origin endpoint
const experimentBucketEndpoint = 'my-experiment.s3.amazonaws.com';
// Custom Origin (S3 Static Website Hosting) endpoint
// const experimentBucketEndpoint = 'my-experiment.s3-website-eu-west-1.amazonaws.com';
/* S3 Origin */
const experimentOrigin = {
s3: {
authMethod: 'origin-access-identity',
domainName: experimentBucketEndpoint,
path: '',
region: experimentBucketRegion
}
}
/* Custom Origin */
// const experimentOrigin = {
// custom: {
// domainName: experimentBucketEndpoint,
// port: 80,
// protocol: 'http',
// path: '',
// readTimeout: 5,
// keepaliveTimeout: 5,
// sslProtocols: ['TLSv1', 'TLSv1.1'],
// customHeaders: {}
// }
// }
// Origin Request handler
// 1) If the source cookie is not present, decide a source randomly and send back a redirect with Set-Cookie and Cache-Control=no-store
// 2) If the source cookie is present and is 'experiment', change the orgin and host header to point the experiment bucket
// 3) If the source cookie has any other value, forward the request as-is to the default origin (main)
exports.handler = (event, context, callback) => {
console.log('Received event:', JSON.stringify(event, null, 2));
const request = event.Records[0].cf.request;
const headers = request.headers;
// Look for source cookie
const source = getSource(headers);
// If Source is undecided roll dice and send directly a Redirect with the Set-Cookie and Cache-Control=no-store
if ( !source ) {
const newSource = ( Math.random() < experimentTraffic ) ? sourceExperiment : sourceMain;
console.log('Dice rolled. Source:', newSource);
// Send a redirect with Set-Cookie header and Cache-control no-store
const response = {
status: 302,
headers: {
'cache-control': [{
key: 'Cache-Control',
value: 'no-store'
}],
'set-cookie': [{
key: 'Set-Cookie',
value: `${sourceCoookie}=${newSource}; Path=/`
}],
'location': [{
key: 'Location',
value: request.uri
}]
}
}
// Send response
console.log('Sending Response:', JSON.stringify(response, null, 2));
callback(null, response);
return;
}
// If Source is Experiment, change Origin and Host header
if ( source === sourceExperiment ) {
console.log('Setting Origin to experiment bucket');
// Specify Origin
request.origin = experimentOrigin;
// Also set Host header to prevent “The request signature we calculated does not match the signature you provided” error
headers['host'] = [{key: 'host', value: experimentBucketEndpoint }];
}
// No need to change anything if Source was Main or undefined
console.log('Request forwarded:', JSON.stringify(request, null, 2));
callback(null, request);
};
// Decide source based on source cookie.
const getSource = function(headers) {
const sourceMainCookie = `${sourceCoookie}=${sourceMain}`;
const sourceExperimenCookie = `${sourceCoookie}=${sourceExperiment}`;
// Remember a single cookie header entry may contains multiple cookies
if (headers.cookie) {
// ...ugly but simple enough for now
for (let i = 0; i < headers.cookie.length; i++) {
if (headers.cookie[i].value.indexOf(sourceExperimenCookie) >= 0) {
console.log('Experiment Source cookie found');
return sourceExperiment;
}
if (headers.cookie[i].value.indexOf(sourceMainCookie) >= 0) {
console.log('Main Source cookie found');
return sourceMain;
}
}
}
console.log('No Source cookie found (Origin undecided)');
}