Skip to content

Commit 04aebd7

Browse files
First commit
0 parents  commit 04aebd7

13 files changed

Lines changed: 2140 additions & 0 deletions

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# package directories
2+
node_modules
3+
jspm_packages
4+
5+
# Serverless directories
6+
.serverless
7+
.webpack
8+
9+
# custom
10+
dummy-payloads
11+
dist/*.json
12+
.DS_Store

dist/originResponse.zip

76.5 KB
Binary file not shown.

dist/viewerOverride.zip

75.9 KB
Binary file not shown.

dist/viewerRequest.zip

79.3 KB
Binary file not shown.

handlerOriginResponse.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
"use strict";
2+
3+
const helpers = require("./helpers/misc");
4+
const http_helpers = require("./helpers/http");
5+
6+
require("source-map-support").install();
7+
8+
module.exports.originResponse = async (event) => {
9+
let APIDomain;
10+
let crowdhandlerResponseID;
11+
let crowdhandlerToken;
12+
let publicKey;
13+
let requestTime;
14+
15+
// Infer useful information from the request event and save it
16+
let request = event.Records[0].cf.request;
17+
let response = event.Records[0].cf.response;
18+
const requestHeaders = request.headers;
19+
const uri = request.uri;
20+
21+
// Don't try and queue static assets
22+
let fileExtension = uri.split(".").pop();
23+
24+
// No need to execute anymore of this script if the request is for a static file.
25+
const creativeAssetExtensions = helpers.creativeAssetExtensions;
26+
if (creativeAssetExtensions.indexOf(fileExtension) !== -1) {
27+
console.log("Static file detected");
28+
return response;
29+
}
30+
31+
// Environment Setup
32+
(function () {
33+
// Guard against the crowdhandlerResponseID value coming back null from the API
34+
try {
35+
if (requestHeaders["x-ch-responseID"]) {
36+
crowdhandlerResponseID = requestHeaders["x-ch-responseID"][0].value;
37+
}
38+
} catch (error) {
39+
console.error(error);
40+
}
41+
42+
// Handle lack of valid token i.e. partial API responses for unprotected rooms.
43+
try {
44+
//Make sure we don't set invalid values
45+
const validToken = /(.*\d+.*)/
46+
47+
if (requestHeaders["x-ch-crowdhandler-token"] && validToken.test(requestHeaders["x-ch-crowdhandler-token"][0].value) === true) {
48+
crowdhandlerToken = requestHeaders["x-ch-crowdhandler-token"][0].value;
49+
}
50+
} catch (error) {
51+
console.error(error);
52+
return response;
53+
}
54+
55+
APIDomain = requestHeaders["x-ch-api-endpoint"][0].value;
56+
publicKey = requestHeaders["x-ch-public-key"][0].value;
57+
requestTime = requestHeaders["x-ch-request-time"][0].value;
58+
})();
59+
60+
// If we don't have a valid crowdhandlerToken by this stage return response.
61+
if (!crowdhandlerToken) {
62+
return response;
63+
}
64+
65+
// Requested Domain
66+
const host = requestHeaders.host[0].value;
67+
68+
// Set cookies
69+
(function () {
70+
if (response.headers["set-cookie"]) {
71+
response.headers["set-cookie"].push({
72+
key: "Set-Cookie",
73+
value: `crowdhandler=${crowdhandlerToken}; path=/; Secure; HttpOnly`,
74+
});
75+
response.headers["set-cookie"].push({
76+
key: "Set-Cookie",
77+
value: `crowdhandler_integration=cloudfront; path=/; Secure;`,
78+
});
79+
} else {
80+
response.headers["set-cookie"] = [
81+
{
82+
key: "Set-Cookie",
83+
value: `crowdhandler=${crowdhandlerToken}; path=/; Secure; HttpOnly`,
84+
},
85+
];
86+
response.headers["set-cookie"].push({
87+
key: "Set-Cookie",
88+
value: `crowdhandler_integration=cloudfront; path=/; Secure;`,
89+
});
90+
}
91+
})();
92+
93+
const totalLoadTime = Date.now() - requestTime;
94+
95+
async function sendPageLoadTime() {
96+
let response;
97+
try {
98+
response = await http_helpers.httpPUT(
99+
{
100+
hostname: APIDomain,
101+
port: 443,
102+
path: `/v1/responses/${crowdhandlerResponseID}`,
103+
method: "PUT",
104+
headers: {
105+
"x-api-key": publicKey,
106+
"Content-Type": "application/json",
107+
},
108+
},
109+
JSON.stringify({
110+
httpCode: 200,
111+
sampleRate: 100,
112+
time: totalLoadTime,
113+
})
114+
);
115+
} catch (error) {
116+
console.error(error);
117+
}
118+
}
119+
120+
await sendPageLoadTime();
121+
122+
return response;
123+
};

handlerViewerOverride.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"use strict";
2+
3+
const helpers = require("./helpers/misc");
4+
const http_helpers = require("./helpers/http");
5+
6+
require("source-map-support").install();
7+
8+
module.exports.viewerOverride = async (event) => {
9+
let request = event.Records[0].cf.request;
10+
let queryString = request.querystring;
11+
// Trim /ch/
12+
let uri = request.uri.substring(4);
13+
14+
// If we have a URI after trimming it means we have been sent a slug that can be used.
15+
let fallbackPath = `/?${queryString}`;
16+
let templateDomain = "wait.crowdhandler.com";
17+
let templatePath;
18+
if (uri) {
19+
templatePath = `/${uri}`;
20+
} else {
21+
templatePath = fallbackPath;
22+
}
23+
24+
// Template fetch with retry mechanic.
25+
let fetchCounter = 0;
26+
async function fetchTemplate(retry) {
27+
let headers = {
28+
"Content-Type": "text/html",
29+
};
30+
let response;
31+
fetchCounter++;
32+
33+
if (fetchCounter === 3) {
34+
templatePath = fallbackPath;
35+
}
36+
37+
try {
38+
response = await http_helpers.httpGET({
39+
headers: headers,
40+
hostname: templateDomain,
41+
method: "GET",
42+
path: templatePath,
43+
port: 443,
44+
});
45+
return response;
46+
} catch (error) {
47+
console.log(error);
48+
response = null;
49+
return response;
50+
}
51+
}
52+
53+
let templateBody;
54+
while (!templateBody && fetchCounter < 4) {
55+
templateBody = await fetchTemplate();
56+
}
57+
58+
if (templateBody) {
59+
let healthyResponse = http_helpers.http200Response(templateBody);
60+
return healthyResponse;
61+
// Handle failure to retrieve template
62+
} else {
63+
let errorResponse = http_helpers.error404Response();
64+
throw errorResponse;
65+
}
66+
};

0 commit comments

Comments
 (0)