@webiny/aws-helpers 0.0.0-unstable.78f581c1d2 → 0.0.0-unstable.7be00a75a9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +2 -7
  2. package/README.md +11 -0
  3. package/cloudfrontFunctions/cookies.d.ts +1 -1
  4. package/cloudfrontFunctions/cookies.js +18 -27
  5. package/cloudfrontFunctions/cookies.js.map +1 -1
  6. package/cloudfrontFunctions/headers.d.ts +1 -1
  7. package/cloudfrontFunctions/headers.js +22 -23
  8. package/cloudfrontFunctions/headers.js.map +1 -1
  9. package/cloudfrontFunctions/index.d.ts +6 -6
  10. package/cloudfrontFunctions/index.js +6 -6
  11. package/cloudfrontFunctions/querystring.d.ts +1 -1
  12. package/cloudfrontFunctions/querystring.js +16 -33
  13. package/cloudfrontFunctions/querystring.js.map +1 -1
  14. package/cloudfrontFunctions/redirect.d.ts +1 -1
  15. package/cloudfrontFunctions/redirect.js +19 -21
  16. package/cloudfrontFunctions/redirect.js.map +1 -1
  17. package/cloudfrontFunctions/types.d.ts +6 -6
  18. package/cloudfrontFunctions/types.js +0 -1
  19. package/cloudfrontFunctions/utils.d.ts +1 -1
  20. package/cloudfrontFunctions/utils.js +8 -19
  21. package/cloudfrontFunctions/utils.js.map +1 -1
  22. package/index.d.ts +1 -1
  23. package/index.js +1 -1
  24. package/lambdaEdge/cookies.d.ts +1 -1
  25. package/lambdaEdge/cookies.js +20 -23
  26. package/lambdaEdge/cookies.js.map +1 -1
  27. package/lambdaEdge/headers.d.ts +1 -1
  28. package/lambdaEdge/headers.js +9 -6
  29. package/lambdaEdge/headers.js.map +1 -1
  30. package/lambdaEdge/index.d.ts +7 -7
  31. package/lambdaEdge/index.js +7 -7
  32. package/lambdaEdge/redirect.d.ts +1 -1
  33. package/lambdaEdge/redirect.js +29 -29
  34. package/lambdaEdge/redirect.js.map +1 -1
  35. package/lambdaEdge/request.d.ts +1 -1
  36. package/lambdaEdge/request.js +26 -19
  37. package/lambdaEdge/request.js.map +1 -1
  38. package/lambdaEdge/response.d.ts +1 -1
  39. package/lambdaEdge/response.js +10 -7
  40. package/lambdaEdge/response.js.map +1 -1
  41. package/lambdaEdge/types.d.ts +8 -8
  42. package/lambdaEdge/types.js +0 -1
  43. package/lambdaEdge/utils.d.ts +1 -1
  44. package/lambdaEdge/utils.js +8 -5
  45. package/lambdaEdge/utils.js.map +1 -1
  46. package/package.json +11 -8
  47. package/rslib-runtime.js +14 -0
  48. package/rslib-runtime.js.map +1 -0
  49. package/stagedRollouts/functions/adminOriginRequest.js +24 -27
  50. package/stagedRollouts/functions/adminOriginRequest.js.map +1 -1
  51. package/stagedRollouts/functions/configOriginRequest.js +48 -48
  52. package/stagedRollouts/functions/configOriginRequest.js.map +1 -1
  53. package/stagedRollouts/functions/originRequest.js +15 -14
  54. package/stagedRollouts/functions/originRequest.js.map +1 -1
  55. package/stagedRollouts/functions/viewerRequest.js +20 -40
  56. package/stagedRollouts/functions/viewerRequest.js.map +1 -1
  57. package/stagedRollouts/functions/viewerResponse.js +12 -16
  58. package/stagedRollouts/functions/viewerResponse.js.map +1 -1
  59. package/stagedRollouts/utils/common.js +8 -5
  60. package/stagedRollouts/utils/common.js.map +1 -1
  61. package/stagedRollouts/utils/headerBlacklist.js +30 -12
  62. package/stagedRollouts/utils/headerBlacklist.js.map +1 -1
  63. package/stagedRollouts/utils/loadOriginPage.d.ts +1 -1
  64. package/stagedRollouts/utils/loadOriginPage.js +75 -98
  65. package/stagedRollouts/utils/loadOriginPage.js.map +1 -1
  66. package/stagedRollouts/utils/loadTrafficSplittingConfig.d.ts +2 -2
  67. package/stagedRollouts/utils/loadTrafficSplittingConfig.js +39 -57
  68. package/stagedRollouts/utils/loadTrafficSplittingConfig.js.map +1 -1
  69. package/stagedRollouts/utils/loadVariantOrigin.d.ts +2 -2
  70. package/stagedRollouts/utils/loadVariantOrigin.js +45 -77
  71. package/stagedRollouts/utils/loadVariantOrigin.js.map +1 -1
  72. package/stagedRollouts/utils/log.js +6 -7
  73. package/stagedRollouts/utils/log.js.map +1 -1
  74. package/cloudfrontFunctions/index.js.map +0 -1
  75. package/cloudfrontFunctions/types.js.map +0 -1
  76. package/index.js.map +0 -1
  77. package/lambdaEdge/index.js.map +0 -1
  78. package/lambdaEdge/types.js.map +0 -1
@@ -1,18 +1,14 @@
1
- import { defineCloudfrontFunctionResponseHandler, setResponseCookie } from "../../cloudfrontFunctions";
2
- import { variantRandomKey } from "../utils/common";
3
- defineCloudfrontFunctionResponseHandler(event => {
4
- var _request$headers$vari;
5
-
6
- const request = event.request;
7
- const response = event.response;
8
- const variantRandom = (_request$headers$vari = request.headers[variantRandomKey]) === null || _request$headers$vari === void 0 ? void 0 : _request$headers$vari.value;
9
-
10
- if (variantRandom) {
11
- setResponseCookie(response, {
12
- name: variantRandomKey,
13
- value: variantRandom
1
+ import { defineCloudfrontFunctionResponseHandler, setResponseCookie } from "../../cloudfrontFunctions/index.js";
2
+ import { variantRandomKey } from "../utils/common.js";
3
+ defineCloudfrontFunctionResponseHandler((event)=>{
4
+ const request = event.request;
5
+ const response = event.response;
6
+ const variantRandom = request.headers[variantRandomKey]?.value;
7
+ if (variantRandom) setResponseCookie(response, {
8
+ name: variantRandomKey,
9
+ value: variantRandom
14
10
  });
15
- }
11
+ return response;
12
+ });
16
13
 
17
- return response;
18
- });
14
+ //# sourceMappingURL=viewerResponse.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["defineCloudfrontFunctionResponseHandler","setResponseCookie","variantRandomKey","event","request","response","variantRandom","headers","value","name"],"sources":["viewerResponse.ts"],"sourcesContent":["import { defineCloudfrontFunctionResponseHandler, setResponseCookie } from \"~/cloudfrontFunctions\";\n\nimport { variantRandomKey } from \"../utils/common\";\n\ndefineCloudfrontFunctionResponseHandler(event => {\n const request = event.request;\n const response = event.response;\n\n const variantRandom = request.headers[variantRandomKey]?.value;\n if (variantRandom) {\n setResponseCookie(response, {\n name: variantRandomKey,\n value: variantRandom\n });\n }\n\n return response;\n});\n"],"mappings":"AAAA,SAASA,uCAAT,EAAkDC,iBAAlD;AAEA,SAASC,gBAAT;AAEAF,uCAAuC,CAACG,KAAK,IAAI;EAAA;;EAC7C,MAAMC,OAAO,GAAGD,KAAK,CAACC,OAAtB;EACA,MAAMC,QAAQ,GAAGF,KAAK,CAACE,QAAvB;EAEA,MAAMC,aAAa,4BAAGF,OAAO,CAACG,OAAR,CAAgBL,gBAAhB,CAAH,0DAAG,sBAAmCM,KAAzD;;EACA,IAAIF,aAAJ,EAAmB;IACfL,iBAAiB,CAACI,QAAD,EAAW;MACxBI,IAAI,EAAEP,gBADkB;MAExBM,KAAK,EAAEF;IAFiB,CAAX,CAAjB;EAIH;;EAED,OAAOD,QAAP;AACH,CAbsC,CAAvC"}
1
+ {"version":3,"file":"stagedRollouts/functions/viewerResponse.js","sources":["../../../src/stagedRollouts/functions/viewerResponse.ts"],"sourcesContent":["import {\n defineCloudfrontFunctionResponseHandler,\n setResponseCookie\n} from \"~/cloudfrontFunctions/index.js\";\n\nimport { variantRandomKey } from \"../utils/common.js\";\n\ndefineCloudfrontFunctionResponseHandler(event => {\n const request = event.request;\n const response = event.response;\n\n const variantRandom = request.headers[variantRandomKey]?.value;\n if (variantRandom) {\n setResponseCookie(response, {\n name: variantRandomKey,\n value: variantRandom\n });\n }\n\n return response;\n});\n"],"names":["defineCloudfrontFunctionResponseHandler","event","request","response","variantRandom","variantRandomKey","setResponseCookie"],"mappings":";;AAOAA,wCAAwCC,CAAAA;IACpC,MAAMC,UAAUD,MAAM,OAAO;IAC7B,MAAME,WAAWF,MAAM,QAAQ;IAE/B,MAAMG,gBAAgBF,QAAQ,OAAO,CAACG,iBAAiB,EAAE;IACzD,IAAID,eACAE,kBAAkBH,UAAU;QACxB,MAAME;QACN,OAAOD;IACX;IAGJ,OAAOD;AACX"}
@@ -1,5 +1,8 @@
1
- export const variantFixedKey = "webiny-variant-fixed";
2
- export const variantRandomKey = "webiny-variant-random";
3
- export function pointsToFile(uri) {
4
- return /\/[^/]+\.[^/]+$/.test(uri);
5
- }
1
+ const variantFixedKey = "webiny-variant-fixed";
2
+ const variantRandomKey = "webiny-variant-random";
3
+ function pointsToFile(uri) {
4
+ return /\/[^/]+\.[^/]+$/.test(uri);
5
+ }
6
+ export { pointsToFile, variantFixedKey, variantRandomKey };
7
+
8
+ //# sourceMappingURL=common.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["variantFixedKey","variantRandomKey","pointsToFile","uri","test"],"sources":["common.ts"],"sourcesContent":["export const variantFixedKey = \"webiny-variant-fixed\";\nexport const variantRandomKey = \"webiny-variant-random\";\n\nexport function pointsToFile(uri: string) {\n return /\\/[^/]+\\.[^/]+$/.test(uri);\n}\n"],"mappings":"AAAA,OAAO,MAAMA,eAAe,GAAG,sBAAxB;AACP,OAAO,MAAMC,gBAAgB,GAAG,uBAAzB;AAEP,OAAO,SAASC,YAAT,CAAsBC,GAAtB,EAAmC;EACtC,OAAO,kBAAkBC,IAAlB,CAAuBD,GAAvB,CAAP;AACH"}
1
+ {"version":3,"file":"stagedRollouts/utils/common.js","sources":["../../../src/stagedRollouts/utils/common.ts"],"sourcesContent":["export const variantFixedKey = \"webiny-variant-fixed\";\nexport const variantRandomKey = \"webiny-variant-random\";\n\nexport function pointsToFile(uri: string) {\n return /\\/[^/]+\\.[^/]+$/.test(uri);\n}\n"],"names":["variantFixedKey","variantRandomKey","pointsToFile","uri"],"mappings":"AAAO,MAAMA,kBAAkB;AACxB,MAAMC,mBAAmB;AAEzB,SAASC,aAAaC,GAAW;IACpC,OAAO,kBAAkB,IAAI,CAACA;AAClC"}
@@ -1,13 +1,31 @@
1
- const blacklistedHeaders = new Set([// blacklisted headers
2
- "connection", "expect", "keep-Alive", "proxy-authenticate", "proxy-authorization", "proxy-connection", "trailer", "upgrade", "x-accel-buffering", "x-accel-charset", "x-accel-limit-rate", "x-accel-redirect", "x-cache", "x-forwarded-proto", "x-real-op", // readonly headers
3
- "content-length", "transfer-encoding", "via"]);
4
- const blacklistedHeadersRegex = [/^x-amz-cf-/, /^x-edge-/];
5
- /**
6
- * Some headers cannot be modified with lambda edge.
7
- * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html
8
- */
1
+ const blacklistedHeaders = new Set([
2
+ "connection",
3
+ "expect",
4
+ "keep-Alive",
5
+ "proxy-authenticate",
6
+ "proxy-authorization",
7
+ "proxy-connection",
8
+ "trailer",
9
+ "upgrade",
10
+ "x-accel-buffering",
11
+ "x-accel-charset",
12
+ "x-accel-limit-rate",
13
+ "x-accel-redirect",
14
+ "x-cache",
15
+ "x-forwarded-proto",
16
+ "x-real-op",
17
+ "content-length",
18
+ "transfer-encoding",
19
+ "via"
20
+ ]);
21
+ const blacklistedHeadersRegex = [
22
+ /^x-amz-cf-/,
23
+ /^x-edge-/
24
+ ];
25
+ function isHeaderBlacklisted(header) {
26
+ header = header.toLocaleLowerCase();
27
+ return blacklistedHeaders.has(header) || blacklistedHeadersRegex.some((r)=>r.test(header));
28
+ }
29
+ export { isHeaderBlacklisted };
9
30
 
10
- export function isHeaderBlacklisted(header) {
11
- header = header.toLocaleLowerCase();
12
- return blacklistedHeaders.has(header) || blacklistedHeadersRegex.some(r => r.test(header));
13
- }
31
+ //# sourceMappingURL=headerBlacklist.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["blacklistedHeaders","Set","blacklistedHeadersRegex","isHeaderBlacklisted","header","toLocaleLowerCase","has","some","r","test"],"sources":["headerBlacklist.ts"],"sourcesContent":["const blacklistedHeaders = new Set([\n // blacklisted headers\n \"connection\",\n \"expect\",\n \"keep-Alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"proxy-connection\",\n \"trailer\",\n \"upgrade\",\n \"x-accel-buffering\",\n \"x-accel-charset\",\n \"x-accel-limit-rate\",\n \"x-accel-redirect\",\n \"x-cache\",\n \"x-forwarded-proto\",\n \"x-real-op\",\n // readonly headers\n \"content-length\",\n \"transfer-encoding\",\n \"via\"\n]);\n\nconst blacklistedHeadersRegex = [/^x-amz-cf-/, /^x-edge-/];\n\n/**\n * Some headers cannot be modified with lambda edge.\n * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html\n */\nexport function isHeaderBlacklisted(header: string) {\n header = header.toLocaleLowerCase();\n return blacklistedHeaders.has(header) || blacklistedHeadersRegex.some(r => r.test(header));\n}\n"],"mappings":"AAAA,MAAMA,kBAAkB,GAAG,IAAIC,GAAJ,CAAQ,CAC/B;AACA,YAF+B,EAG/B,QAH+B,EAI/B,YAJ+B,EAK/B,oBAL+B,EAM/B,qBAN+B,EAO/B,kBAP+B,EAQ/B,SAR+B,EAS/B,SAT+B,EAU/B,mBAV+B,EAW/B,iBAX+B,EAY/B,oBAZ+B,EAa/B,kBAb+B,EAc/B,SAd+B,EAe/B,mBAf+B,EAgB/B,WAhB+B,EAiB/B;AACA,gBAlB+B,EAmB/B,mBAnB+B,EAoB/B,KApB+B,CAAR,CAA3B;AAuBA,MAAMC,uBAAuB,GAAG,CAAC,YAAD,EAAe,UAAf,CAAhC;AAEA;AACA;AACA;AACA;;AACA,OAAO,SAASC,mBAAT,CAA6BC,MAA7B,EAA6C;EAChDA,MAAM,GAAGA,MAAM,CAACC,iBAAP,EAAT;EACA,OAAOL,kBAAkB,CAACM,GAAnB,CAAuBF,MAAvB,KAAkCF,uBAAuB,CAACK,IAAxB,CAA6BC,CAAC,IAAIA,CAAC,CAACC,IAAF,CAAOL,MAAP,CAAlC,CAAzC;AACH"}
1
+ {"version":3,"file":"stagedRollouts/utils/headerBlacklist.js","sources":["../../../src/stagedRollouts/utils/headerBlacklist.ts"],"sourcesContent":["const blacklistedHeaders = new Set([\n // blacklisted headers\n \"connection\",\n \"expect\",\n \"keep-Alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"proxy-connection\",\n \"trailer\",\n \"upgrade\",\n \"x-accel-buffering\",\n \"x-accel-charset\",\n \"x-accel-limit-rate\",\n \"x-accel-redirect\",\n \"x-cache\",\n \"x-forwarded-proto\",\n \"x-real-op\",\n // readonly headers\n \"content-length\",\n \"transfer-encoding\",\n \"via\"\n]);\n\nconst blacklistedHeadersRegex = [/^x-amz-cf-/, /^x-edge-/];\n\n/**\n * Some headers cannot be modified with lambda edge.\n * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html\n */\nexport function isHeaderBlacklisted(header: string) {\n header = header.toLocaleLowerCase();\n return blacklistedHeaders.has(header) || blacklistedHeadersRegex.some(r => r.test(header));\n}\n"],"names":["blacklistedHeaders","Set","blacklistedHeadersRegex","isHeaderBlacklisted","header","r"],"mappings":"AAAA,MAAMA,qBAAqB,IAAIC,IAAI;IAE/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;CACH;AAED,MAAMC,0BAA0B;IAAC;IAAc;CAAW;AAMnD,SAASC,oBAAoBC,MAAc;IAC9CA,SAASA,OAAO,iBAAiB;IACjC,OAAOJ,mBAAmB,GAAG,CAACI,WAAWF,wBAAwB,IAAI,CAACG,CAAAA,IAAKA,EAAE,IAAI,CAACD;AACtF"}
@@ -1,4 +1,4 @@
1
- import { CloudFrontResponse } from "../../lambdaEdge";
1
+ import type { CloudFrontResponse } from "../../lambdaEdge/index.js";
2
2
  /**
3
3
  * Load HTML from origin and perform transformation of URLs to absolute
4
4
  * @param domain Domain of the origin cloudfront
@@ -1,107 +1,84 @@
1
1
  import { get } from "https";
2
2
  import { load } from "cheerio";
3
- import { parse as parseSrcset, stringify as stringifySrcset } from "srcset";
4
- import { isHeaderBlacklisted } from "./headerBlacklist";
5
- import { logDebug } from "./log";
6
- /**
7
- * Load HTML from origin and perform transformation of URLs to absolute
8
- * @param domain Domain of the origin cloudfront
9
- * @param path Path of the file we want to retrieve
10
- * @returns Response object
11
- */
12
-
13
- export function loadOriginPage(domain, path) {
14
- return new Promise((resolve, reject) => {
15
- logDebug(`Pulling page from ${domain}${path}`);
16
- let responseBody = "";
17
- const req = get({
18
- hostname: domain,
19
- port: 443,
20
- path: path
21
- }, res => {
22
- res.on("data", chunk => responseBody += chunk);
23
- res.on("end", () => {
24
- logDebug(`Parsing page`);
25
- const html = parseHtml(responseBody, domain);
26
- const response = {
27
- body: html,
28
- status: "200",
29
- statusDescription: "ok",
30
- headers: {}
31
- }; // Rewrite headers from the HTTP response
32
-
33
- for (const header of Object.keys(res.headers)) {
34
- // We cannot set any header we want.
35
- // CloudFront is restricting us from setting or changing some headers.
36
- if (isHeaderBlacklisted(header)) {
37
- continue;
38
- }
39
-
40
- const value = res.headers[header];
41
-
42
- if (Array.isArray(value)) {
43
- response.headers[header] = value.map(h => ({
44
- key: header,
45
- value: h
46
- }));
47
- } else if (value) {
48
- response.headers[header] = [{
49
- key: header,
50
- value: value
51
- }];
52
- }
53
- }
54
-
55
- logDebug(`Page parsed`);
56
- resolve(response);
57
- });
3
+ import { parseSrcset, stringifySrcset } from "srcset";
4
+ import { isHeaderBlacklisted } from "./headerBlacklist.js";
5
+ import { logDebug } from "./log.js";
6
+ function loadOriginPage(domain, path) {
7
+ return new Promise((resolve, reject)=>{
8
+ logDebug(`Pulling page from ${domain}${path}`);
9
+ let responseBody = "";
10
+ const req = get({
11
+ hostname: domain,
12
+ port: 443,
13
+ path: path
14
+ }, (res)=>{
15
+ res.on("data", (chunk)=>responseBody += chunk);
16
+ res.on("end", ()=>{
17
+ logDebug("Parsing page");
18
+ const html = parseHtml(responseBody, domain);
19
+ const response = {
20
+ body: html,
21
+ status: "200",
22
+ statusDescription: "ok",
23
+ headers: {}
24
+ };
25
+ for (const header of Object.keys(res.headers)){
26
+ if (isHeaderBlacklisted(header)) continue;
27
+ const value = res.headers[header];
28
+ if (Array.isArray(value)) response.headers[header] = value.map((h)=>({
29
+ key: header,
30
+ value: h
31
+ }));
32
+ else if (value) response.headers[header] = [
33
+ {
34
+ key: header,
35
+ value: value
36
+ }
37
+ ];
38
+ }
39
+ logDebug("Page parsed");
40
+ resolve(response);
41
+ });
42
+ });
43
+ req.on("error", (e)=>{
44
+ reject({
45
+ statusCode: 500,
46
+ body: e.message
47
+ });
48
+ });
58
49
  });
59
- req.on("error", e => {
60
- reject({
61
- statusCode: 500,
62
- body: e.message
63
- });
64
- });
65
- });
66
50
  }
67
-
68
51
  function parseHtml(html, domain) {
69
- const doc = load(html);
70
- const host = `https://${domain}`;
71
- doc("head > link").each((_i, el) => {
72
- prefixUrl(el, "href", host);
73
- });
74
- doc("script").each((_i, el) => {
75
- prefixUrl(el, "src", host);
76
- });
77
- doc("body").find("img").each((_i, el) => {
78
- prefixUrl(el, "src", host); // Handle also srcset property for responsive images.
79
-
80
- const srcset = el.attribs["srcset"];
81
-
82
- if (srcset) {
83
- const srcsetParsed = parseSrcset(srcset);
84
- const srcsetRebased = srcsetParsed.map(src => {
85
- if (src.url.startsWith("/")) {
86
- return {
87
- url: host + src.url,
88
- density: src.density,
89
- width: src.width
90
- };
52
+ const doc = load(html);
53
+ const host = `https://${domain}`;
54
+ doc("head > link").each((_i, el)=>{
55
+ prefixUrl(el, "href", host);
56
+ });
57
+ doc("script").each((_i, el)=>{
58
+ prefixUrl(el, "src", host);
59
+ });
60
+ doc("body").find("img").each((_i, el)=>{
61
+ prefixUrl(el, "src", host);
62
+ const srcset = el.attribs["srcset"];
63
+ if (srcset) {
64
+ const srcsetParsed = parseSrcset(srcset);
65
+ const srcsetRebased = srcsetParsed.map((src)=>{
66
+ if (src.url.startsWith("/")) return {
67
+ url: host + src.url,
68
+ density: src.density,
69
+ width: src.width
70
+ };
71
+ return src;
72
+ });
73
+ el.attribs["srcset"] = stringifySrcset(srcsetRebased);
91
74
  }
92
-
93
- return src;
94
- });
95
- el.attribs["srcset"] = stringifySrcset(srcsetRebased);
96
- }
97
- });
98
- return doc.html();
75
+ });
76
+ return doc.html();
99
77
  }
100
-
101
78
  function prefixUrl(el, attr, host) {
102
- const href = el.attribs[attr];
79
+ const href = el.attribs[attr];
80
+ if (href && href.startsWith("/")) el.attribs[attr] = host + href;
81
+ }
82
+ export { loadOriginPage };
103
83
 
104
- if (href && href.startsWith("/")) {
105
- el.attribs[attr] = host + href;
106
- }
107
- }
84
+ //# sourceMappingURL=loadOriginPage.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["get","load","parse","parseSrcset","stringify","stringifySrcset","isHeaderBlacklisted","logDebug","loadOriginPage","domain","path","Promise","resolve","reject","responseBody","req","hostname","port","res","on","chunk","html","parseHtml","response","body","status","statusDescription","headers","header","Object","keys","value","Array","isArray","map","h","key","e","statusCode","message","doc","host","each","_i","el","prefixUrl","find","srcset","attribs","srcsetParsed","srcsetRebased","src","url","startsWith","density","width","attr","href"],"sources":["loadOriginPage.ts"],"sourcesContent":["import { CloudFrontResponse } from \"~/lambdaEdge\";\nimport { get } from \"https\";\nimport { load, Element } from \"cheerio\";\nimport { parse as parseSrcset, stringify as stringifySrcset, SrcSetDefinition } from \"srcset\";\nimport { isHeaderBlacklisted } from \"./headerBlacklist\";\nimport { logDebug } from \"./log\";\n\n/**\n * Load HTML from origin and perform transformation of URLs to absolute\n * @param domain Domain of the origin cloudfront\n * @param path Path of the file we want to retrieve\n * @returns Response object\n */\nexport function loadOriginPage(domain: string, path: string) {\n return new Promise<CloudFrontResponse>((resolve, reject) => {\n logDebug(`Pulling page from ${domain}${path}`);\n let responseBody = \"\";\n const req = get(\n {\n hostname: domain,\n port: 443,\n path: path\n },\n res => {\n res.on(\"data\", chunk => (responseBody += chunk));\n res.on(\"end\", () => {\n logDebug(`Parsing page`);\n const html = parseHtml(responseBody, domain);\n const response: CloudFrontResponse = {\n body: html,\n status: \"200\",\n statusDescription: \"ok\",\n headers: {}\n };\n\n // Rewrite headers from the HTTP response\n for (const header of Object.keys(res.headers)) {\n // We cannot set any header we want.\n // CloudFront is restricting us from setting or changing some headers.\n if (isHeaderBlacklisted(header)) {\n continue;\n }\n\n const value = res.headers[header];\n if (Array.isArray(value)) {\n response.headers[header] = value.map(h => ({\n key: header,\n value: h\n }));\n } else if (value) {\n response.headers[header] = [\n {\n key: header,\n value: value\n }\n ];\n }\n }\n\n logDebug(`Page parsed`);\n resolve(response);\n });\n }\n );\n\n req.on(\"error\", e => {\n reject({\n statusCode: 500,\n body: e.message\n });\n });\n });\n}\n\nfunction parseHtml(html: string, domain: string) {\n const doc = load(html);\n const host = `https://${domain}`;\n\n doc(\"head > link\").each((_i, el) => {\n prefixUrl(el, \"href\", host);\n });\n\n doc(\"script\").each((_i, el) => {\n prefixUrl(el, \"src\", host);\n });\n\n doc(\"body\")\n .find(\"img\")\n .each((_i, el) => {\n prefixUrl(el, \"src\", host);\n\n // Handle also srcset property for responsive images.\n const srcset = el.attribs[\"srcset\"];\n if (srcset) {\n const srcsetParsed = parseSrcset(srcset);\n const srcsetRebased = srcsetParsed.map<SrcSetDefinition>(src => {\n if (src.url.startsWith(\"/\")) {\n return {\n url: host + src.url,\n density: src.density,\n width: src.width\n };\n }\n\n return src;\n });\n\n el.attribs[\"srcset\"] = stringifySrcset(srcsetRebased);\n }\n });\n\n return doc.html();\n}\n\nfunction prefixUrl(el: Element, attr: string, host: string) {\n const href = el.attribs[attr];\n if (href && href.startsWith(\"/\")) {\n el.attribs[attr] = host + href;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stagedRollouts/utils/loadOriginPage.js","sources":["../../../src/stagedRollouts/utils/loadOriginPage.ts"],"sourcesContent":["import type { CloudFrontResponse } from \"~/lambdaEdge/index.js\";\nimport { get } from \"https\";\nimport { load } from \"cheerio\";\nimport type { SrcSetDefinition } from \"srcset\";\nimport { parseSrcset, stringifySrcset } from \"srcset\";\nimport { isHeaderBlacklisted } from \"./headerBlacklist.js\";\nimport { logDebug } from \"./log.js\";\n\n// TODO cheerio does not have Element type, so we define it here\ninterface Element {\n attribs: {\n [key: string]: string;\n };\n}\n\n/**\n * Load HTML from origin and perform transformation of URLs to absolute\n * @param domain Domain of the origin cloudfront\n * @param path Path of the file we want to retrieve\n * @returns Response object\n */\nexport function loadOriginPage(domain: string, path: string) {\n return new Promise<CloudFrontResponse>((resolve, reject) => {\n logDebug(`Pulling page from ${domain}${path}`);\n let responseBody = \"\";\n const req = get(\n {\n hostname: domain,\n port: 443,\n path: path\n },\n res => {\n res.on(\"data\", chunk => (responseBody += chunk));\n res.on(\"end\", () => {\n logDebug(`Parsing page`);\n const html = parseHtml(responseBody, domain);\n const response: CloudFrontResponse = {\n body: html,\n status: \"200\",\n statusDescription: \"ok\",\n headers: {}\n };\n\n // Rewrite headers from the HTTP response\n for (const header of Object.keys(res.headers)) {\n // We cannot set any header we want.\n // CloudFront is restricting us from setting or changing some headers.\n if (isHeaderBlacklisted(header)) {\n continue;\n }\n\n const value = res.headers[header];\n if (Array.isArray(value)) {\n response.headers[header] = value.map(h => ({\n key: header,\n value: h\n }));\n } else if (value) {\n response.headers[header] = [\n {\n key: header,\n value: value\n }\n ];\n }\n }\n\n logDebug(`Page parsed`);\n resolve(response);\n });\n }\n );\n\n req.on(\"error\", e => {\n reject({\n statusCode: 500,\n body: e.message\n });\n });\n });\n}\n\nfunction parseHtml(html: string, domain: string) {\n const doc = load(html);\n const host = `https://${domain}`;\n\n doc(\"head > link\").each((_i, el) => {\n prefixUrl(el, \"href\", host);\n });\n\n doc(\"script\").each((_i, el) => {\n prefixUrl(el, \"src\", host);\n });\n\n doc(\"body\")\n .find(\"img\")\n .each((_i, el) => {\n prefixUrl(el, \"src\", host);\n\n // Handle also srcset property for responsive images.\n const srcset = el.attribs[\"srcset\"];\n if (srcset) {\n const srcsetParsed = parseSrcset(srcset);\n const srcsetRebased = srcsetParsed.map<SrcSetDefinition>(src => {\n if (src.url.startsWith(\"/\")) {\n return {\n url: host + src.url,\n density: src.density,\n width: src.width\n };\n }\n\n return src;\n });\n\n el.attribs[\"srcset\"] = stringifySrcset(srcsetRebased);\n }\n });\n\n return doc.html();\n}\n\nfunction prefixUrl(el: Element, attr: string, host: string) {\n const href = el.attribs[attr];\n if (href && href.startsWith(\"/\")) {\n el.attribs[attr] = host + href;\n }\n}\n"],"names":["loadOriginPage","domain","path","Promise","resolve","reject","logDebug","responseBody","req","get","res","chunk","html","parseHtml","response","header","Object","isHeaderBlacklisted","value","Array","h","e","doc","load","host","_i","el","prefixUrl","srcset","srcsetParsed","parseSrcset","srcsetRebased","src","stringifySrcset","attr","href"],"mappings":";;;;;AAqBO,SAASA,eAAeC,MAAc,EAAEC,IAAY;IACvD,OAAO,IAAIC,QAA4B,CAACC,SAASC;QAC7CC,SAAS,CAAC,kBAAkB,EAAEL,SAASC,MAAM;QAC7C,IAAIK,eAAe;QACnB,MAAMC,MAAMC,IACR;YACI,UAAUR;YACV,MAAM;YACN,MAAMC;QACV,GACAQ,CAAAA;YACIA,IAAI,EAAE,CAAC,QAAQC,CAAAA,QAAUJ,gBAAgBI;YACzCD,IAAI,EAAE,CAAC,OAAO;gBACVJ,SAAS;gBACT,MAAMM,OAAOC,UAAUN,cAAcN;gBACrC,MAAMa,WAA+B;oBACjC,MAAMF;oBACN,QAAQ;oBACR,mBAAmB;oBACnB,SAAS,CAAC;gBACd;gBAGA,KAAK,MAAMG,UAAUC,OAAO,IAAI,CAACN,IAAI,OAAO,EAAG;oBAG3C,IAAIO,oBAAoBF,SACpB;oBAGJ,MAAMG,QAAQR,IAAI,OAAO,CAACK,OAAO;oBACjC,IAAII,MAAM,OAAO,CAACD,QACdJ,SAAS,OAAO,CAACC,OAAO,GAAGG,MAAM,GAAG,CAACE,CAAAA,IAAM;4BACvC,KAAKL;4BACL,OAAOK;wBACX;yBACG,IAAIF,OACPJ,SAAS,OAAO,CAACC,OAAO,GAAG;wBACvB;4BACI,KAAKA;4BACL,OAAOG;wBACX;qBACH;gBAET;gBAEAZ,SAAS;gBACTF,QAAQU;YACZ;QACJ;QAGJN,IAAI,EAAE,CAAC,SAASa,CAAAA;YACZhB,OAAO;gBACH,YAAY;gBACZ,MAAMgB,EAAE,OAAO;YACnB;QACJ;IACJ;AACJ;AAEA,SAASR,UAAUD,IAAY,EAAEX,MAAc;IAC3C,MAAMqB,MAAMC,KAAKX;IACjB,MAAMY,OAAO,CAAC,QAAQ,EAAEvB,QAAQ;IAEhCqB,IAAI,eAAe,IAAI,CAAC,CAACG,IAAIC;QACzBC,UAAUD,IAAI,QAAQF;IAC1B;IAEAF,IAAI,UAAU,IAAI,CAAC,CAACG,IAAIC;QACpBC,UAAUD,IAAI,OAAOF;IACzB;IAEAF,IAAI,QACC,IAAI,CAAC,OACL,IAAI,CAAC,CAACG,IAAIC;QACPC,UAAUD,IAAI,OAAOF;QAGrB,MAAMI,SAASF,GAAG,OAAO,CAAC,SAAS;QACnC,IAAIE,QAAQ;YACR,MAAMC,eAAeC,YAAYF;YACjC,MAAMG,gBAAgBF,aAAa,GAAG,CAAmBG,CAAAA;gBACrD,IAAIA,IAAI,GAAG,CAAC,UAAU,CAAC,MACnB,OAAO;oBACH,KAAKR,OAAOQ,IAAI,GAAG;oBACnB,SAASA,IAAI,OAAO;oBACpB,OAAOA,IAAI,KAAK;gBACpB;gBAGJ,OAAOA;YACX;YAEAN,GAAG,OAAO,CAAC,SAAS,GAAGO,gBAAgBF;QAC3C;IACJ;IAEJ,OAAOT,IAAI,IAAI;AACnB;AAEA,SAASK,UAAUD,EAAW,EAAEQ,IAAY,EAAEV,IAAY;IACtD,MAAMW,OAAOT,GAAG,OAAO,CAACQ,KAAK;IAC7B,IAAIC,QAAQA,KAAK,UAAU,CAAC,MACxBT,GAAG,OAAO,CAACQ,KAAK,GAAGV,OAAOW;AAElC"}
@@ -1,9 +1,9 @@
1
- import { CloudFrontRequestEvent } from "../../lambdaEdge";
1
+ import type { CloudFrontRequestEvent } from "../../lambdaEdge/index.js";
2
2
  export interface VariantConfig {
3
3
  domain: string;
4
4
  weight: number;
5
5
  }
6
- export declare type GatewayConfig = Record<string, VariantConfig>;
6
+ export type GatewayConfig = Record<string, VariantConfig>;
7
7
  /**
8
8
  * Loads traffic splitting config.
9
9
  * It will, however not call WCP directly, but serve it from a locally cached file,
@@ -1,65 +1,47 @@
1
1
  import { get } from "https";
2
- import { logDebug } from "./log"; // Config file has a fixed URL within CDN, so it can be properly cached.
3
- // This way we achieve better performance, because CDN does not have to call WCP API for config every time,
4
- // but it can use it's own cache for a lookup.
5
-
6
- const configPath = "/_config"; // Config is locally cached within live lambda for a short time (1 minute).
7
- // Config must be cached per domain.
8
- // Otherwise cache will spill over different apps, because we may share this lambda.
9
-
2
+ import { logDebug } from "./log.js";
3
+ const configPath = "/_config";
10
4
  const configCache = new Map();
11
-
12
- /**
13
- * Loads traffic splitting config.
14
- * It will, however not call WCP directly, but serve it from a locally cached file,
15
- * as explained here https://www.notion.so/webiny/How-traffic-config-is-cached-2c8db57ca2b547a2b2fb1adf378cd191
16
- */
17
- export async function loadTrafficSplittingConfig(event) {
18
- // Retrieve domain of the CloudFront distribution.
19
- // We need it to make sure we cache config per application.
20
- // For example API and website could share the same lambda instance.
21
- // So we cache it separately for each domain (each CloudFront).
22
- const domain = event.Records[0].cf.config.distributionDomainName;
23
- let config = configCache.get(domain);
24
-
25
- if (!config || isCacheExpired(config.timestamp)) {
26
- logDebug("No config in cache");
27
- config = {
28
- config: await loadConfigCore(domain),
29
- timestamp: Date.now()
30
- };
31
- configCache.set(domain, config);
32
- }
33
-
34
- return config.config;
5
+ async function loadTrafficSplittingConfig(event) {
6
+ const domain = event.Records[0].cf.config.distributionDomainName;
7
+ let config = configCache.get(domain);
8
+ if (!config || isCacheExpired(config.timestamp)) {
9
+ logDebug("No config in cache");
10
+ config = {
11
+ config: await loadConfigCore(domain),
12
+ timestamp: Date.now()
13
+ };
14
+ configCache.set(domain, config);
15
+ }
16
+ return config.config;
35
17
  }
36
-
37
18
  function loadConfigCore(domain) {
38
- return new Promise((resolve, reject) => {
39
- let dataString = "";
40
- const req = get({
41
- hostname: domain,
42
- port: 443,
43
- path: configPath
44
- }, function (res) {
45
- res.on("data", chunk => {
46
- dataString += chunk;
47
- });
48
- res.on("end", () => {
49
- resolve(JSON.parse(dataString));
50
- });
51
- });
52
- req.on("error", e => {
53
- reject({
54
- statusCode: 500,
55
- body: e.message
56
- });
19
+ return new Promise((resolve, reject)=>{
20
+ let dataString = "";
21
+ const req = get({
22
+ hostname: domain,
23
+ port: 443,
24
+ path: configPath
25
+ }, function(res) {
26
+ res.on("data", (chunk)=>{
27
+ dataString += chunk;
28
+ });
29
+ res.on("end", ()=>{
30
+ resolve(JSON.parse(dataString));
31
+ });
32
+ });
33
+ req.on("error", (e)=>{
34
+ reject({
35
+ statusCode: 500,
36
+ body: e.message
37
+ });
38
+ });
57
39
  });
58
- });
59
40
  }
60
-
61
41
  function isCacheExpired(timestamp) {
62
- const ttl = 60 * 1000; // 1 minute
42
+ const ttl = 60000;
43
+ return Date.now() - timestamp > ttl;
44
+ }
45
+ export { loadTrafficSplittingConfig };
63
46
 
64
- return Date.now() - timestamp > ttl;
65
- }
47
+ //# sourceMappingURL=loadTrafficSplittingConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["get","logDebug","configPath","configCache","Map","loadTrafficSplittingConfig","event","domain","Records","cf","config","distributionDomainName","isCacheExpired","timestamp","loadConfigCore","Date","now","set","Promise","resolve","reject","dataString","req","hostname","port","path","res","on","chunk","JSON","parse","e","statusCode","body","message","ttl"],"sources":["loadTrafficSplittingConfig.ts"],"sourcesContent":["import { get } from \"https\";\nimport { CloudFrontRequestEvent } from \"~/lambdaEdge\";\nimport { logDebug } from \"./log\";\n\n// Config file has a fixed URL within CDN, so it can be properly cached.\n// This way we achieve better performance, because CDN does not have to call WCP API for config every time,\n// but it can use it's own cache for a lookup.\nconst configPath = \"/_config\";\n\n// Config is locally cached within live lambda for a short time (1 minute).\n// Config must be cached per domain.\n// Otherwise cache will spill over different apps, because we may share this lambda.\nconst configCache = new Map<string, GatewayConfigCache>();\n\ninterface GatewayConfigCache {\n config: GatewayConfig;\n timestamp: number;\n}\n\nexport interface VariantConfig {\n domain: string;\n weight: number;\n}\n\nexport type GatewayConfig = Record<string, VariantConfig>;\n\n/**\n * Loads traffic splitting config.\n * It will, however not call WCP directly, but serve it from a locally cached file,\n * as explained here https://www.notion.so/webiny/How-traffic-config-is-cached-2c8db57ca2b547a2b2fb1adf378cd191\n */\nexport async function loadTrafficSplittingConfig(event: CloudFrontRequestEvent) {\n // Retrieve domain of the CloudFront distribution.\n // We need it to make sure we cache config per application.\n // For example API and website could share the same lambda instance.\n // So we cache it separately for each domain (each CloudFront).\n const domain = event.Records[0].cf.config.distributionDomainName;\n\n let config = configCache.get(domain);\n if (!config || isCacheExpired(config.timestamp)) {\n logDebug(\"No config in cache\");\n config = {\n config: await loadConfigCore(domain),\n timestamp: Date.now()\n };\n\n configCache.set(domain, config);\n }\n\n return config.config;\n}\n\nfunction loadConfigCore(domain: string) {\n return new Promise<GatewayConfig>((resolve, reject) => {\n let dataString = \"\";\n\n const req = get(\n {\n hostname: domain,\n port: 443,\n path: configPath\n },\n function (res) {\n res.on(\"data\", chunk => {\n dataString += chunk;\n });\n res.on(\"end\", () => {\n resolve(JSON.parse(dataString));\n });\n }\n );\n\n req.on(\"error\", e => {\n reject({\n statusCode: 500,\n body: e.message\n });\n });\n });\n}\n\nfunction isCacheExpired(timestamp: number) {\n const ttl = 60 * 1000; // 1 minute\n return Date.now() - timestamp > ttl;\n}\n"],"mappings":"AAAA,SAASA,GAAT,QAAoB,OAApB;AAEA,SAASC,QAAT,gB,CAEA;AACA;AACA;;AACA,MAAMC,UAAU,GAAG,UAAnB,C,CAEA;AACA;AACA;;AACA,MAAMC,WAAW,GAAG,IAAIC,GAAJ,EAApB;;AAcA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,0BAAf,CAA0CC,KAA1C,EAAyE;EAC5E;EACA;EACA;EACA;EACA,MAAMC,MAAM,GAAGD,KAAK,CAACE,OAAN,CAAc,CAAd,EAAiBC,EAAjB,CAAoBC,MAApB,CAA2BC,sBAA1C;EAEA,IAAID,MAAM,GAAGP,WAAW,CAACH,GAAZ,CAAgBO,MAAhB,CAAb;;EACA,IAAI,CAACG,MAAD,IAAWE,cAAc,CAACF,MAAM,CAACG,SAAR,CAA7B,EAAiD;IAC7CZ,QAAQ,CAAC,oBAAD,CAAR;IACAS,MAAM,GAAG;MACLA,MAAM,EAAE,MAAMI,cAAc,CAACP,MAAD,CADvB;MAELM,SAAS,EAAEE,IAAI,CAACC,GAAL;IAFN,CAAT;IAKAb,WAAW,CAACc,GAAZ,CAAgBV,MAAhB,EAAwBG,MAAxB;EACH;;EAED,OAAOA,MAAM,CAACA,MAAd;AACH;;AAED,SAASI,cAAT,CAAwBP,MAAxB,EAAwC;EACpC,OAAO,IAAIW,OAAJ,CAA2B,CAACC,OAAD,EAAUC,MAAV,KAAqB;IACnD,IAAIC,UAAU,GAAG,EAAjB;IAEA,MAAMC,GAAG,GAAGtB,GAAG,CACX;MACIuB,QAAQ,EAAEhB,MADd;MAEIiB,IAAI,EAAE,GAFV;MAGIC,IAAI,EAAEvB;IAHV,CADW,EAMX,UAAUwB,GAAV,EAAe;MACXA,GAAG,CAACC,EAAJ,CAAO,MAAP,EAAeC,KAAK,IAAI;QACpBP,UAAU,IAAIO,KAAd;MACH,CAFD;MAGAF,GAAG,CAACC,EAAJ,CAAO,KAAP,EAAc,MAAM;QAChBR,OAAO,CAACU,IAAI,CAACC,KAAL,CAAWT,UAAX,CAAD,CAAP;MACH,CAFD;IAGH,CAbU,CAAf;IAgBAC,GAAG,CAACK,EAAJ,CAAO,OAAP,EAAgBI,CAAC,IAAI;MACjBX,MAAM,CAAC;QACHY,UAAU,EAAE,GADT;QAEHC,IAAI,EAAEF,CAAC,CAACG;MAFL,CAAD,CAAN;IAIH,CALD;EAMH,CAzBM,CAAP;AA0BH;;AAED,SAAStB,cAAT,CAAwBC,SAAxB,EAA2C;EACvC,MAAMsB,GAAG,GAAG,KAAK,IAAjB,CADuC,CAChB;;EACvB,OAAOpB,IAAI,CAACC,GAAL,KAAaH,SAAb,GAAyBsB,GAAhC;AACH"}
1
+ {"version":3,"file":"stagedRollouts/utils/loadTrafficSplittingConfig.js","sources":["../../../src/stagedRollouts/utils/loadTrafficSplittingConfig.ts"],"sourcesContent":["import { get } from \"https\";\nimport type { CloudFrontRequestEvent } from \"~/lambdaEdge/index.js\";\nimport { logDebug } from \"./log.js\";\n\n// Config file has a fixed URL within CDN, so it can be properly cached.\n// This way we achieve better performance, because CDN does not have to call WCP API for config every time,\n// but it can use it's own cache for a lookup.\nconst configPath = \"/_config\";\n\n// Config is locally cached within live lambda for a short time (1 minute).\n// Config must be cached per domain.\n// Otherwise cache will spill over different apps, because we may share this lambda.\nconst configCache = new Map<string, GatewayConfigCache>();\n\ninterface GatewayConfigCache {\n config: GatewayConfig;\n timestamp: number;\n}\n\nexport interface VariantConfig {\n domain: string;\n weight: number;\n}\n\nexport type GatewayConfig = Record<string, VariantConfig>;\n\n/**\n * Loads traffic splitting config.\n * It will, however not call WCP directly, but serve it from a locally cached file,\n * as explained here https://www.notion.so/webiny/How-traffic-config-is-cached-2c8db57ca2b547a2b2fb1adf378cd191\n */\nexport async function loadTrafficSplittingConfig(event: CloudFrontRequestEvent) {\n // Retrieve domain of the CloudFront distribution.\n // We need it to make sure we cache config per application.\n // For example API and website could share the same lambda instance.\n // So we cache it separately for each domain (each CloudFront).\n const domain = event.Records[0].cf.config.distributionDomainName;\n\n let config = configCache.get(domain);\n if (!config || isCacheExpired(config.timestamp)) {\n logDebug(\"No config in cache\");\n config = {\n config: await loadConfigCore(domain),\n timestamp: Date.now()\n };\n\n configCache.set(domain, config);\n }\n\n return config.config;\n}\n\nfunction loadConfigCore(domain: string) {\n return new Promise<GatewayConfig>((resolve, reject) => {\n let dataString = \"\";\n\n const req = get(\n {\n hostname: domain,\n port: 443,\n path: configPath\n },\n function (res) {\n res.on(\"data\", chunk => {\n dataString += chunk;\n });\n res.on(\"end\", () => {\n resolve(JSON.parse(dataString));\n });\n }\n );\n\n req.on(\"error\", e => {\n reject({\n statusCode: 500,\n body: e.message\n });\n });\n });\n}\n\nfunction isCacheExpired(timestamp: number) {\n const ttl = 60 * 1000; // 1 minute\n return Date.now() - timestamp > ttl;\n}\n"],"names":["configPath","configCache","Map","loadTrafficSplittingConfig","event","domain","config","isCacheExpired","logDebug","loadConfigCore","Date","Promise","resolve","reject","dataString","req","get","res","chunk","JSON","e","timestamp","ttl"],"mappings":";;AAOA,MAAMA,aAAa;AAKnB,MAAMC,cAAc,IAAIC;AAmBjB,eAAeC,2BAA2BC,KAA6B;IAK1E,MAAMC,SAASD,MAAM,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,sBAAsB;IAEhE,IAAIE,SAASL,YAAY,GAAG,CAACI;IAC7B,IAAI,CAACC,UAAUC,eAAeD,OAAO,SAAS,GAAG;QAC7CE,SAAS;QACTF,SAAS;YACL,QAAQ,MAAMG,eAAeJ;YAC7B,WAAWK,KAAK,GAAG;QACvB;QAEAT,YAAY,GAAG,CAACI,QAAQC;IAC5B;IAEA,OAAOA,OAAO,MAAM;AACxB;AAEA,SAASG,eAAeJ,MAAc;IAClC,OAAO,IAAIM,QAAuB,CAACC,SAASC;QACxC,IAAIC,aAAa;QAEjB,MAAMC,MAAMC,IACR;YACI,UAAUX;YACV,MAAM;YACN,MAAML;QACV,GACA,SAAUiB,GAAG;YACTA,IAAI,EAAE,CAAC,QAAQC,CAAAA;gBACXJ,cAAcI;YAClB;YACAD,IAAI,EAAE,CAAC,OAAO;gBACVL,QAAQO,KAAK,KAAK,CAACL;YACvB;QACJ;QAGJC,IAAI,EAAE,CAAC,SAASK,CAAAA;YACZP,OAAO;gBACH,YAAY;gBACZ,MAAMO,EAAE,OAAO;YACnB;QACJ;IACJ;AACJ;AAEA,SAASb,eAAec,SAAiB;IACrC,MAAMC,MAAM;IACZ,OAAOZ,KAAK,GAAG,KAAKW,YAAYC;AACpC"}
@@ -1,4 +1,4 @@
1
- import { CloudFrontRequestEvent } from "../../lambdaEdge";
1
+ import type { CloudFrontRequestEvent } from "../../lambdaEdge/index.js";
2
2
  export declare function loadVariantOrigin(event: CloudFrontRequestEvent): Promise<import("aws-lambda").CloudFrontRequest | import("aws-lambda").CloudFrontResultResponse | {
3
- variant: import("./loadTrafficSplittingConfig").VariantConfig;
3
+ variant: import("../utils/loadTrafficSplittingConfig.js").VariantConfig;
4
4
  }>;