@rayselfs/cf-rule-engine 1.5.0
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.
- package/README.md +276 -0
- package/dist/adapters/cf-function.cjs +10 -0
- package/dist/adapters/cf-function.d.cts +2 -0
- package/dist/adapters/cf-function.d.ts +2 -0
- package/dist/adapters/cf-function.js +10 -0
- package/dist/adapters/lambda-edge.cjs +10 -0
- package/dist/adapters/lambda-edge.d.cts +2 -0
- package/dist/adapters/lambda-edge.d.ts +2 -0
- package/dist/adapters/lambda-edge.js +10 -0
- package/dist/behaviors/construct-response.cjs +7 -0
- package/dist/behaviors/construct-response.d.cts +62 -0
- package/dist/behaviors/construct-response.d.ts +62 -0
- package/dist/behaviors/construct-response.js +7 -0
- package/dist/behaviors/copy-header.cjs +7 -0
- package/dist/behaviors/copy-header.d.cts +27 -0
- package/dist/behaviors/copy-header.d.ts +27 -0
- package/dist/behaviors/copy-header.js +7 -0
- package/dist/behaviors/directory-index.cjs +7 -0
- package/dist/behaviors/directory-index.d.cts +33 -0
- package/dist/behaviors/directory-index.d.ts +33 -0
- package/dist/behaviors/directory-index.js +7 -0
- package/dist/behaviors/image-optimize.cjs +9 -0
- package/dist/behaviors/image-optimize.d.cts +103 -0
- package/dist/behaviors/image-optimize.d.ts +103 -0
- package/dist/behaviors/image-optimize.js +9 -0
- package/dist/behaviors/index.cjs +126 -0
- package/dist/behaviors/index.d.cts +46 -0
- package/dist/behaviors/index.d.ts +46 -0
- package/dist/behaviors/index.js +126 -0
- package/dist/behaviors/redirect.cjs +7 -0
- package/dist/behaviors/redirect.d.cts +44 -0
- package/dist/behaviors/redirect.d.ts +44 -0
- package/dist/behaviors/redirect.js +7 -0
- package/dist/behaviors/remove-response-headers.cjs +7 -0
- package/dist/behaviors/remove-response-headers.d.cts +27 -0
- package/dist/behaviors/remove-response-headers.d.ts +27 -0
- package/dist/behaviors/remove-response-headers.js +7 -0
- package/dist/behaviors/rewrite-uri.cjs +7 -0
- package/dist/behaviors/rewrite-uri.d.cts +43 -0
- package/dist/behaviors/rewrite-uri.d.ts +43 -0
- package/dist/behaviors/rewrite-uri.js +7 -0
- package/dist/behaviors/set-cache-control.cjs +7 -0
- package/dist/behaviors/set-cache-control.d.cts +29 -0
- package/dist/behaviors/set-cache-control.d.ts +29 -0
- package/dist/behaviors/set-cache-control.js +7 -0
- package/dist/behaviors/set-cors-headers.cjs +7 -0
- package/dist/behaviors/set-cors-headers.d.cts +76 -0
- package/dist/behaviors/set-cors-headers.d.ts +76 -0
- package/dist/behaviors/set-cors-headers.js +7 -0
- package/dist/behaviors/set-csp.cjs +7 -0
- package/dist/behaviors/set-csp.d.cts +48 -0
- package/dist/behaviors/set-csp.d.ts +48 -0
- package/dist/behaviors/set-csp.js +7 -0
- package/dist/behaviors/set-request-header.cjs +7 -0
- package/dist/behaviors/set-request-header.d.cts +26 -0
- package/dist/behaviors/set-request-header.d.ts +26 -0
- package/dist/behaviors/set-request-header.js +7 -0
- package/dist/behaviors/set-response-header.cjs +7 -0
- package/dist/behaviors/set-response-header.d.cts +28 -0
- package/dist/behaviors/set-response-header.d.ts +28 -0
- package/dist/behaviors/set-response-header.js +7 -0
- package/dist/behaviors/set-security-headers.cjs +7 -0
- package/dist/behaviors/set-security-headers.d.cts +55 -0
- package/dist/behaviors/set-security-headers.d.ts +55 -0
- package/dist/behaviors/set-security-headers.js +7 -0
- package/dist/behaviors/strip-query-params.cjs +7 -0
- package/dist/behaviors/strip-query-params.d.cts +25 -0
- package/dist/behaviors/strip-query-params.d.ts +25 -0
- package/dist/behaviors/strip-query-params.js +7 -0
- package/dist/cf-function-D27hUVtN.d.cts +70 -0
- package/dist/cf-function-u0PvbW_s.d.ts +70 -0
- package/dist/chunk-2DE6WPPL.js +21 -0
- package/dist/chunk-32SMWYAF.cjs +13 -0
- package/dist/chunk-3BBLG4IX.cjs +132 -0
- package/dist/chunk-3PVDUC5M.js +12 -0
- package/dist/chunk-5CPBXZ4X.js +12 -0
- package/dist/chunk-5PT5X62W.js +98 -0
- package/dist/chunk-63WIEBQB.cjs +50 -0
- package/dist/chunk-6DBZBV2M.js +42 -0
- package/dist/chunk-75ZPJI57.cjs +9 -0
- package/dist/chunk-B4WEJSEZ.cjs +14 -0
- package/dist/chunk-BDNPQ7AU.js +21 -0
- package/dist/chunk-BUAIBB3N.js +14 -0
- package/dist/chunk-BZQJYOU2.js +12 -0
- package/dist/chunk-C32DL3EP.js +13 -0
- package/dist/chunk-CF5PWWTF.cjs +15 -0
- package/dist/chunk-CV234DQT.cjs +14 -0
- package/dist/chunk-D47P7HVZ.cjs +12 -0
- package/dist/chunk-DSSFFJWL.js +38 -0
- package/dist/chunk-FTP7NLKX.js +29 -0
- package/dist/chunk-G7JGTBTT.cjs +8 -0
- package/dist/chunk-GK5JX7OM.cjs +39 -0
- package/dist/chunk-H2LO6MQG.js +50 -0
- package/dist/chunk-IBXAK2A4.cjs +21 -0
- package/dist/chunk-JGJW7D2N.cjs +12 -0
- package/dist/chunk-JU5WX5RU.cjs +21 -0
- package/dist/chunk-KW5YBTSD.js +12 -0
- package/dist/chunk-KZ72PI2A.js +0 -0
- package/dist/chunk-L7NBJ4JA.cjs +12 -0
- package/dist/chunk-LBJUCJF2.js +14 -0
- package/dist/chunk-LNQPYKGG.js +20 -0
- package/dist/chunk-LO2BO3RU.js +15 -0
- package/dist/chunk-LSCC62CZ.cjs +13 -0
- package/dist/chunk-LTLBEBKL.cjs +42 -0
- package/dist/chunk-M5KUQBDW.js +17 -0
- package/dist/chunk-MEHWLQLR.cjs +1 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-MRPTC74I.cjs +29 -0
- package/dist/chunk-MSES76XK.cjs +14 -0
- package/dist/chunk-MVGYPBYB.cjs +16 -0
- package/dist/chunk-NPMGSPNL.js +88 -0
- package/dist/chunk-OSGZTNTS.cjs +42 -0
- package/dist/chunk-OSZWDCTS.cjs +12 -0
- package/dist/chunk-OTFDML3K.cjs +11 -0
- package/dist/chunk-PPUHEL4H.cjs +17 -0
- package/dist/chunk-PY3JMRDG.js +11 -0
- package/dist/chunk-Q4NP4C3B.js +47 -0
- package/dist/chunk-R7WXS7BI.js +42 -0
- package/dist/chunk-RBBKFG5J.js +14 -0
- package/dist/chunk-S2AAATFN.js +16 -0
- package/dist/chunk-SAXDN5NS.cjs +88 -0
- package/dist/chunk-SGEBNQR2.cjs +14 -0
- package/dist/chunk-SOBTD7AD.js +39 -0
- package/dist/chunk-SRQF5UEJ.js +13 -0
- package/dist/chunk-TQLJIT4H.cjs +98 -0
- package/dist/chunk-U54FZCOH.cjs +14 -0
- package/dist/chunk-UD456E4I.js +8 -0
- package/dist/chunk-UI6LKDJI.cjs +19 -0
- package/dist/chunk-UKB5JAX4.js +32 -0
- package/dist/chunk-VEEOQ7TS.cjs +8 -0
- package/dist/chunk-VQCRSBWL.js +19 -0
- package/dist/chunk-WEBU4R5C.js +132 -0
- package/dist/chunk-WKYMSRCD.cjs +47 -0
- package/dist/chunk-WW7YVRAI.cjs +32 -0
- package/dist/chunk-WWSRNCUP.cjs +38 -0
- package/dist/chunk-XLSZ5RB7.js +8 -0
- package/dist/chunk-XPQG5IML.js +14 -0
- package/dist/chunk-XUI4Y22M.js +20 -0
- package/dist/chunk-YVUR35RN.cjs +20 -0
- package/dist/chunk-ZTMSH34E.js +14 -0
- package/dist/chunk-ZXS23HXA.cjs +20 -0
- package/dist/core/rule.cjs +17 -0
- package/dist/core/rule.d.cts +101 -0
- package/dist/core/rule.d.ts +101 -0
- package/dist/core/rule.js +17 -0
- package/dist/core/types.cjs +1 -0
- package/dist/core/types.d.cts +53 -0
- package/dist/core/types.d.ts +53 -0
- package/dist/core/types.js +1 -0
- package/dist/criteria/country-is.cjs +7 -0
- package/dist/criteria/country-is.d.cts +35 -0
- package/dist/criteria/country-is.d.ts +35 -0
- package/dist/criteria/country-is.js +7 -0
- package/dist/criteria/file-extension.cjs +7 -0
- package/dist/criteria/file-extension.d.cts +32 -0
- package/dist/criteria/file-extension.d.ts +32 -0
- package/dist/criteria/file-extension.js +7 -0
- package/dist/criteria/header-contains.cjs +7 -0
- package/dist/criteria/header-contains.d.cts +33 -0
- package/dist/criteria/header-contains.d.ts +33 -0
- package/dist/criteria/header-contains.js +7 -0
- package/dist/criteria/header-equals.cjs +7 -0
- package/dist/criteria/header-equals.d.cts +31 -0
- package/dist/criteria/header-equals.d.ts +31 -0
- package/dist/criteria/header-equals.js +7 -0
- package/dist/criteria/hostname-is.cjs +7 -0
- package/dist/criteria/hostname-is.d.cts +22 -0
- package/dist/criteria/hostname-is.d.ts +22 -0
- package/dist/criteria/hostname-is.js +7 -0
- package/dist/criteria/index.cjs +49 -0
- package/dist/criteria/index.d.cts +12 -0
- package/dist/criteria/index.d.ts +12 -0
- package/dist/criteria/index.js +49 -0
- package/dist/criteria/ip-cidr.cjs +8 -0
- package/dist/criteria/ip-cidr.d.cts +31 -0
- package/dist/criteria/ip-cidr.d.ts +31 -0
- package/dist/criteria/ip-cidr.js +8 -0
- package/dist/criteria/method-is.cjs +7 -0
- package/dist/criteria/method-is.d.cts +29 -0
- package/dist/criteria/method-is.d.ts +29 -0
- package/dist/criteria/method-is.js +7 -0
- package/dist/criteria/path-equals.cjs +7 -0
- package/dist/criteria/path-equals.d.cts +22 -0
- package/dist/criteria/path-equals.d.ts +22 -0
- package/dist/criteria/path-equals.js +7 -0
- package/dist/criteria/path-matches.cjs +8 -0
- package/dist/criteria/path-matches.d.cts +22 -0
- package/dist/criteria/path-matches.d.ts +22 -0
- package/dist/criteria/path-matches.js +8 -0
- package/dist/criteria/path-prefix.cjs +7 -0
- package/dist/criteria/path-prefix.d.cts +21 -0
- package/dist/criteria/path-prefix.d.ts +21 -0
- package/dist/criteria/path-prefix.js +7 -0
- package/dist/criteria/user-agent-matches.cjs +8 -0
- package/dist/criteria/user-agent-matches.d.cts +32 -0
- package/dist/criteria/user-agent-matches.d.ts +32 -0
- package/dist/criteria/user-agent-matches.js +8 -0
- package/dist/helpers/index.cjs +42 -0
- package/dist/helpers/index.d.cts +34 -0
- package/dist/helpers/index.d.ts +34 -0
- package/dist/helpers/index.js +42 -0
- package/dist/helpers/preflight-request.cjs +8 -0
- package/dist/helpers/preflight-request.d.cts +38 -0
- package/dist/helpers/preflight-request.d.ts +38 -0
- package/dist/helpers/preflight-request.js +8 -0
- package/dist/helpers/send-country-code.cjs +8 -0
- package/dist/helpers/send-country-code.d.cts +35 -0
- package/dist/helpers/send-country-code.d.ts +35 -0
- package/dist/helpers/send-country-code.js +8 -0
- package/dist/helpers/staging-whitelist.cjs +14 -0
- package/dist/helpers/staging-whitelist.d.cts +73 -0
- package/dist/helpers/staging-whitelist.d.ts +73 -0
- package/dist/helpers/staging-whitelist.js +14 -0
- package/dist/index.cjs +26 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +26 -0
- package/dist/lambda-edge-D15Nf__n.d.ts +66 -0
- package/dist/lambda-edge-DxTOa2cg.d.cts +66 -0
- package/dist/shared/cidr.cjs +11 -0
- package/dist/shared/cidr.d.cts +8 -0
- package/dist/shared/cidr.d.ts +8 -0
- package/dist/shared/cidr.js +11 -0
- package/dist/shared/wildcard.cjs +11 -0
- package/dist/shared/wildcard.d.cts +8 -0
- package/dist/shared/wildcard.d.ts +8 -0
- package/dist/shared/wildcard.js +11 -0
- package/package.json +65 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ipCidr
|
|
3
|
+
} from "./chunk-KW5YBTSD.js";
|
|
4
|
+
import {
|
|
5
|
+
pathMatches
|
|
6
|
+
} from "./chunk-LO2BO3RU.js";
|
|
7
|
+
import {
|
|
8
|
+
userAgentMatches
|
|
9
|
+
} from "./chunk-S2AAATFN.js";
|
|
10
|
+
import {
|
|
11
|
+
all,
|
|
12
|
+
not,
|
|
13
|
+
rule
|
|
14
|
+
} from "./chunk-Q4NP4C3B.js";
|
|
15
|
+
import {
|
|
16
|
+
redirect
|
|
17
|
+
} from "./chunk-DSSFFJWL.js";
|
|
18
|
+
|
|
19
|
+
// src/helpers/staging-whitelist.ts
|
|
20
|
+
function stagingWhitelist(options) {
|
|
21
|
+
const userAgents = options.userAgents ?? [];
|
|
22
|
+
const bypassPaths = options.bypassPaths ?? [];
|
|
23
|
+
const criteria = [not(ipCidr(options.cidrs)), not(userAgentMatches(userAgents))];
|
|
24
|
+
if (bypassPaths.length > 0) {
|
|
25
|
+
criteria.push(not(pathMatches(bypassPaths)));
|
|
26
|
+
}
|
|
27
|
+
return rule(all(criteria), redirect(302, options.redirectUrl));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
stagingWhitelist
|
|
32
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/behaviors/set-security-headers.ts
|
|
2
|
+
function setSecurityHeaders(options) {
|
|
3
|
+
const hsts = options?.hsts ?? "max-age=31536000; includeSubDomains";
|
|
4
|
+
const xFrameOptions = options?.xFrameOptions ?? "SAMEORIGIN";
|
|
5
|
+
const xContentTypeOptions = options?.xContentTypeOptions ?? "nosniff";
|
|
6
|
+
return (_request, response) => {
|
|
7
|
+
return Object.assign({}, response, {
|
|
8
|
+
headers: Object.assign({}, response.headers, {
|
|
9
|
+
"strict-transport-security": { value: hsts },
|
|
10
|
+
"x-frame-options": { value: xFrameOptions },
|
|
11
|
+
"x-content-type-options": { value: xContentTypeOptions }
|
|
12
|
+
})
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
setSecurityHeaders
|
|
19
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runRules
|
|
3
|
+
} from "./chunk-Q4NP4C3B.js";
|
|
4
|
+
import {
|
|
5
|
+
__export
|
|
6
|
+
} from "./chunk-MLKGABMK.js";
|
|
7
|
+
|
|
8
|
+
// src/adapters/lambda-edge.ts
|
|
9
|
+
var lambda_edge_exports = {};
|
|
10
|
+
__export(lambda_edge_exports, {
|
|
11
|
+
defineViewerRequest: () => defineViewerRequest,
|
|
12
|
+
defineViewerResponse: () => defineViewerResponse
|
|
13
|
+
});
|
|
14
|
+
function normalizeHeaders(headers) {
|
|
15
|
+
const result = {};
|
|
16
|
+
const entries = Object.entries(headers ?? {});
|
|
17
|
+
for (let i = 0; i < entries.length; i++) {
|
|
18
|
+
const entry = entries[i];
|
|
19
|
+
const key = entry[0];
|
|
20
|
+
const arr = entry[1];
|
|
21
|
+
if (arr.length > 0) result[key.toLowerCase()] = { value: arr[0].value };
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
function denormalizeHeaders(headers) {
|
|
26
|
+
const result = {};
|
|
27
|
+
const entries = Object.entries(headers);
|
|
28
|
+
for (let i = 0; i < entries.length; i++) {
|
|
29
|
+
const entry = entries[i];
|
|
30
|
+
const key = entry[0];
|
|
31
|
+
const value = entry[1].value;
|
|
32
|
+
result[key] = [{ key, value }];
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
function parseQuerystring(qs) {
|
|
37
|
+
if (!qs) return {};
|
|
38
|
+
return Object.fromEntries(
|
|
39
|
+
qs.split("&").map((p) => {
|
|
40
|
+
const parts = p.split("=");
|
|
41
|
+
const k = parts[0];
|
|
42
|
+
const v = parts[1] || "";
|
|
43
|
+
return [k, { value: v }];
|
|
44
|
+
})
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function serializeQuerystring(qs) {
|
|
48
|
+
const qsEntries = Object.entries(qs);
|
|
49
|
+
const parts = [];
|
|
50
|
+
for (let i = 0; i < qsEntries.length; i++) {
|
|
51
|
+
parts.push(qsEntries[i][0] + "=" + qsEntries[i][1].value);
|
|
52
|
+
}
|
|
53
|
+
return parts.join("&");
|
|
54
|
+
}
|
|
55
|
+
function defineViewerRequest(rules) {
|
|
56
|
+
return async (event) => {
|
|
57
|
+
const ev = event;
|
|
58
|
+
const records = ev.Records;
|
|
59
|
+
const cf = records[0].cf;
|
|
60
|
+
const lambdaReq = cf.request;
|
|
61
|
+
const req = {
|
|
62
|
+
uri: lambdaReq.uri,
|
|
63
|
+
method: lambdaReq.method,
|
|
64
|
+
protocol: "https",
|
|
65
|
+
querystring: parseQuerystring(lambdaReq.querystring ?? ""),
|
|
66
|
+
headers: normalizeHeaders(
|
|
67
|
+
lambdaReq.headers ?? {}
|
|
68
|
+
),
|
|
69
|
+
clientIp: lambdaReq.clientIp ?? ""
|
|
70
|
+
};
|
|
71
|
+
const result = runRules(rules, req);
|
|
72
|
+
if (result.action === "respond") {
|
|
73
|
+
return {
|
|
74
|
+
status: String(result.response.statusCode),
|
|
75
|
+
statusDescription: result.response.statusDescription,
|
|
76
|
+
headers: denormalizeHeaders(result.response.headers),
|
|
77
|
+
body: result.response.body ?? ""
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return Object.assign({}, lambdaReq, {
|
|
81
|
+
uri: result.request.uri,
|
|
82
|
+
querystring: serializeQuerystring(result.request.querystring),
|
|
83
|
+
headers: denormalizeHeaders(result.request.headers)
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function defineViewerResponse(responseBehaviors) {
|
|
88
|
+
return async (event) => {
|
|
89
|
+
const ev = event;
|
|
90
|
+
const records = ev.Records;
|
|
91
|
+
const cf = records[0].cf;
|
|
92
|
+
const lambdaReq = cf.request;
|
|
93
|
+
const lambdaRes = cf.response;
|
|
94
|
+
const req = {
|
|
95
|
+
uri: lambdaReq.uri,
|
|
96
|
+
method: lambdaReq.method,
|
|
97
|
+
protocol: "https",
|
|
98
|
+
querystring: parseQuerystring(lambdaReq.querystring ?? ""),
|
|
99
|
+
headers: normalizeHeaders(
|
|
100
|
+
lambdaReq.headers ?? {}
|
|
101
|
+
),
|
|
102
|
+
clientIp: lambdaReq.clientIp ?? ""
|
|
103
|
+
};
|
|
104
|
+
let response = {
|
|
105
|
+
statusCode: parseInt(lambdaRes.status, 10),
|
|
106
|
+
statusDescription: lambdaRes.statusDescription,
|
|
107
|
+
headers: normalizeHeaders(
|
|
108
|
+
lambdaRes.headers ?? {}
|
|
109
|
+
),
|
|
110
|
+
body: lambdaRes.body
|
|
111
|
+
};
|
|
112
|
+
for (let i = 0; i < responseBehaviors.length; i++) {
|
|
113
|
+
const entry = responseBehaviors[i];
|
|
114
|
+
if (typeof entry === "function") {
|
|
115
|
+
response = entry(req, response);
|
|
116
|
+
} else if (!entry.criteria || entry.criteria(req)) {
|
|
117
|
+
response = entry.behavior(req, response);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return Object.assign({}, lambdaRes, {
|
|
121
|
+
status: String(response.statusCode),
|
|
122
|
+
statusDescription: response.statusDescription,
|
|
123
|
+
headers: denormalizeHeaders(response.headers)
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export {
|
|
129
|
+
defineViewerRequest,
|
|
130
|
+
defineViewerResponse,
|
|
131
|
+
lambda_edge_exports
|
|
132
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/core/rule.ts
|
|
2
|
+
function rule(criteriaOrBehavior, behavior) {
|
|
3
|
+
if (behavior === void 0) {
|
|
4
|
+
return { behavior: criteriaOrBehavior };
|
|
5
|
+
}
|
|
6
|
+
return { criteria: criteriaOrBehavior, behavior };
|
|
7
|
+
}
|
|
8
|
+
function all(fns) {
|
|
9
|
+
return (req) => fns.every((fn) => fn(req));
|
|
10
|
+
}
|
|
11
|
+
function any(fns) {
|
|
12
|
+
return (req) => fns.some((fn) => fn(req));
|
|
13
|
+
}
|
|
14
|
+
function not(fn) {
|
|
15
|
+
return (req) => !fn(req);
|
|
16
|
+
}
|
|
17
|
+
function chain(behaviors) {
|
|
18
|
+
return (request) => {
|
|
19
|
+
let current = request;
|
|
20
|
+
for (let i = 0; i < behaviors.length; i++) {
|
|
21
|
+
const result = behaviors[i](current);
|
|
22
|
+
if (result.action === "respond") return result;
|
|
23
|
+
current = result.request;
|
|
24
|
+
}
|
|
25
|
+
return { action: "continue", request: current };
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function runRules(rules, request) {
|
|
29
|
+
for (let i = 0; i < rules.length; i++) {
|
|
30
|
+
const r = rules[i];
|
|
31
|
+
if (!r.criteria || r.criteria(request)) {
|
|
32
|
+
const result = r.behavior(request);
|
|
33
|
+
if (result.action === "respond") return result;
|
|
34
|
+
request = result.request;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { action: "continue", request };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
exports.rule = rule; exports.all = all; exports.any = any; exports.not = not; exports.chain = chain; exports.runRules = runRules;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
|
+
|
|
3
|
+
var _chunkD47P7HVZcjs = require('./chunk-D47P7HVZ.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunkCF5PWWTFcjs = require('./chunk-CF5PWWTF.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _chunkMVGYPBYBcjs = require('./chunk-MVGYPBYB.cjs');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
var _chunkWKYMSRCDcjs = require('./chunk-WKYMSRCD.cjs');
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
var _chunkWWSRNCUPcjs = require('./chunk-WWSRNCUP.cjs');
|
|
18
|
+
|
|
19
|
+
// src/helpers/staging-whitelist.ts
|
|
20
|
+
function stagingWhitelist(options) {
|
|
21
|
+
const userAgents = _nullishCoalesce(options.userAgents, () => ( []));
|
|
22
|
+
const bypassPaths = _nullishCoalesce(options.bypassPaths, () => ( []));
|
|
23
|
+
const criteria = [_chunkWKYMSRCDcjs.not.call(void 0, _chunkD47P7HVZcjs.ipCidr.call(void 0, options.cidrs)), _chunkWKYMSRCDcjs.not.call(void 0, _chunkMVGYPBYBcjs.userAgentMatches.call(void 0, userAgents))];
|
|
24
|
+
if (bypassPaths.length > 0) {
|
|
25
|
+
criteria.push(_chunkWKYMSRCDcjs.not.call(void 0, _chunkCF5PWWTFcjs.pathMatches.call(void 0, bypassPaths)));
|
|
26
|
+
}
|
|
27
|
+
return _chunkWKYMSRCDcjs.rule.call(void 0, _chunkWKYMSRCDcjs.all.call(void 0, criteria), _chunkWWSRNCUPcjs.redirect.call(void 0, 302, options.redirectUrl));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
exports.stagingWhitelist = stagingWhitelist;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/behaviors/redirect.ts
|
|
2
|
+
var statusDescriptions = {
|
|
3
|
+
301: "Moved Permanently",
|
|
4
|
+
302: "Found",
|
|
5
|
+
307: "Temporary Redirect"
|
|
6
|
+
};
|
|
7
|
+
function redirect(statusCode, location, options) {
|
|
8
|
+
return (request) => {
|
|
9
|
+
let finalLocation = location;
|
|
10
|
+
if (_optionalChain([options, 'optionalAccess', _ => _.preserveQuerystring])) {
|
|
11
|
+
const qsEntries = Object.entries(request.querystring);
|
|
12
|
+
const qsParts = [];
|
|
13
|
+
for (let i = 0; i < qsEntries.length; i++) {
|
|
14
|
+
const entry = qsEntries[i];
|
|
15
|
+
qsParts.push(entry[0] + "=" + entry[1].value);
|
|
16
|
+
}
|
|
17
|
+
const qs = qsParts.join("&");
|
|
18
|
+
if (qs) {
|
|
19
|
+
finalLocation = `${location}?${qs}`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
action: "respond",
|
|
24
|
+
response: {
|
|
25
|
+
statusCode,
|
|
26
|
+
statusDescription: statusDescriptions[statusCode],
|
|
27
|
+
headers: {
|
|
28
|
+
location: { value: finalLocation },
|
|
29
|
+
"cache-control": { value: "no-store" }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
exports.redirect = redirect;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/behaviors/strip-query-params.ts
|
|
2
|
+
function stripQueryParams(params) {
|
|
3
|
+
return (request) => {
|
|
4
|
+
const querystring = Object.assign({}, request.querystring);
|
|
5
|
+
for (let i = 0; i < params.length; i++) {
|
|
6
|
+
delete querystring[params[i]];
|
|
7
|
+
}
|
|
8
|
+
return { action: "continue", request: Object.assign({}, request, { querystring }) };
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
stripQueryParams
|
|
14
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/behaviors/set-csp.ts
|
|
2
|
+
function setCsp(options) {
|
|
3
|
+
const dirEntries = Object.entries(options.directives);
|
|
4
|
+
const dirParts = [];
|
|
5
|
+
for (let i = 0; i < dirEntries.length; i++) {
|
|
6
|
+
dirParts.push(dirEntries[i][0] + " " + dirEntries[i][1]);
|
|
7
|
+
}
|
|
8
|
+
const cspValue = dirParts.join("; ");
|
|
9
|
+
return (_request, response) => {
|
|
10
|
+
return Object.assign({}, response, {
|
|
11
|
+
headers: Object.assign({}, response.headers, {
|
|
12
|
+
"content-security-policy": { value: cspValue }
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
setCsp
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/shared/cidr.ts
|
|
2
|
+
function ipToInt(ip) {
|
|
3
|
+
return ip.split(".").reduce((acc, octet) => (acc << 8) + parseInt(octet, 10) >>> 0, 0);
|
|
4
|
+
}
|
|
5
|
+
function inCidr(ip, cidr) {
|
|
6
|
+
const parts = cidr.split("/");
|
|
7
|
+
const range = parts[0];
|
|
8
|
+
const bits = parts[1] || "32";
|
|
9
|
+
const mask = bits === "0" ? 0 : ~0 << 32 - parseInt(bits, 10) >>> 0;
|
|
10
|
+
return (ipToInt(ip) & mask) === (ipToInt(range) & mask);
|
|
11
|
+
}
|
|
12
|
+
function matchesAnyCidr(ip, cidrs) {
|
|
13
|
+
return cidrs.some((cidr) => inCidr(ip, cidr));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
exports.ipToInt = ipToInt; exports.inCidr = inCidr; exports.matchesAnyCidr = matchesAnyCidr;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/behaviors/set-cache-control.ts
|
|
2
|
+
function setCacheControl(value) {
|
|
3
|
+
return (_request, response) => {
|
|
4
|
+
return Object.assign({}, response, {
|
|
5
|
+
headers: Object.assign({}, response.headers, {
|
|
6
|
+
"cache-control": { value }
|
|
7
|
+
})
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
setCacheControl
|
|
14
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/behaviors/set-csp.ts
|
|
2
|
+
function setCsp(options) {
|
|
3
|
+
const dirEntries = Object.entries(options.directives);
|
|
4
|
+
const dirParts = [];
|
|
5
|
+
for (let i = 0; i < dirEntries.length; i++) {
|
|
6
|
+
dirParts.push(dirEntries[i][0] + " " + dirEntries[i][1]);
|
|
7
|
+
}
|
|
8
|
+
const cspValue = dirParts.join("; ");
|
|
9
|
+
return (_request, response) => {
|
|
10
|
+
return Object.assign({}, response, {
|
|
11
|
+
headers: Object.assign({}, response.headers, {
|
|
12
|
+
"content-security-policy": { value: cspValue }
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
exports.setCsp = setCsp;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunkWKYMSRCDcjs = require('../chunk-WKYMSRCD.cjs');
|
|
9
|
+
require('../chunk-75ZPJI57.cjs');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
exports.all = _chunkWKYMSRCDcjs.all; exports.any = _chunkWKYMSRCDcjs.any; exports.chain = _chunkWKYMSRCDcjs.chain; exports.not = _chunkWKYMSRCDcjs.not; exports.rule = _chunkWKYMSRCDcjs.rule; exports.runRules = _chunkWKYMSRCDcjs.runRules;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { CriteriaFn, BehaviorFn, Rule, HttpRequest, BehaviorResult } from './types.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a rule that always runs the given behavior (no criteria guard).
|
|
5
|
+
*
|
|
6
|
+
* @param behavior - The behavior function to execute for every request.
|
|
7
|
+
* @returns A `Rule` object to pass to `defineViewerRequest`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Always set security headers, regardless of path
|
|
12
|
+
* rule(setSecurityHeaders())
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function rule(behavior: BehaviorFn): Rule;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a rule that runs the behavior only when the criteria returns `true`.
|
|
18
|
+
*
|
|
19
|
+
* @param criteria - Guard function; the behavior runs only when this returns `true`.
|
|
20
|
+
* @param behavior - The behavior function to execute when criteria matches.
|
|
21
|
+
* @returns A `Rule` object to pass to `defineViewerRequest`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* // Redirect /old-path to /new-path
|
|
26
|
+
* rule(pathPrefix(['/old-path']), redirect(301, '/new-path'))
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function rule(criteria: CriteriaFn, behavior: BehaviorFn): Rule;
|
|
30
|
+
/**
|
|
31
|
+
* Combines multiple criteria with AND logic — all must return `true`.
|
|
32
|
+
*
|
|
33
|
+
* @param fns - Array of criteria functions to evaluate.
|
|
34
|
+
* @returns A `CriteriaFn` that returns `true` only when every function in `fns` returns `true`.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* rule(all([pathPrefix(['/api/']), methodIs(['POST'])]), constructResponse({ statusCode: 403 }))
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare function all(fns: CriteriaFn[]): CriteriaFn;
|
|
42
|
+
/**
|
|
43
|
+
* Combines multiple criteria with OR logic — at least one must return `true`.
|
|
44
|
+
*
|
|
45
|
+
* @param fns - Array of criteria functions to evaluate.
|
|
46
|
+
* @returns A `CriteriaFn` that returns `true` when any function in `fns` returns `true`.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* rule(any([pathPrefix(['/admin/']), ipCidr(['10.0.0.0/8'])]), redirect(302, '/blocked'))
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare function any(fns: CriteriaFn[]): CriteriaFn;
|
|
54
|
+
/**
|
|
55
|
+
* Negates a criteria function — returns `true` when the wrapped function returns `false`.
|
|
56
|
+
*
|
|
57
|
+
* @param fn - The criteria function to negate.
|
|
58
|
+
* @returns A `CriteriaFn` that returns the logical inverse of `fn`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* // Block all non-internal IPs
|
|
63
|
+
* rule(not(ipCidr(['10.0.0.0/8', '192.168.0.0/16'])), redirect(302, '/blocked'))
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function not(fn: CriteriaFn): CriteriaFn;
|
|
67
|
+
/**
|
|
68
|
+
* Chains multiple behavior functions sequentially, passing the mutated request
|
|
69
|
+
* from each behavior to the next. Stops immediately if any behavior returns
|
|
70
|
+
* `{ action: 'respond' }`.
|
|
71
|
+
*
|
|
72
|
+
* Use this when a single Akamai rule has multiple behaviors that must operate
|
|
73
|
+
* on the same (possibly mutated) request. Without chaining, splitting behaviors
|
|
74
|
+
* into separate `rule()` calls causes each to re-evaluate criteria against
|
|
75
|
+
* the original request — breaking cases where behavior 1 rewrites the URI
|
|
76
|
+
* and behavior 2 must see the rewritten path.
|
|
77
|
+
*
|
|
78
|
+
* @param behaviors - Ordered array of behavior functions to execute in sequence.
|
|
79
|
+
* @returns A single `BehaviorFn` that runs all behaviors in order.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* rule(pathPrefix(['/api/']), chain([rewriteUri('replace', '/v2', '/api'), setRequestHeader('x-api-version', '2')]))
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare function chain(behaviors: BehaviorFn[]): BehaviorFn;
|
|
87
|
+
/**
|
|
88
|
+
* Executes an ordered list of rules against a request, stopping at the first
|
|
89
|
+
* rule whose behavior returns `{ action: 'respond' }`.
|
|
90
|
+
*
|
|
91
|
+
* This is called internally by `defineViewerRequest`; you rarely need to call
|
|
92
|
+
* it directly unless building a custom adapter.
|
|
93
|
+
*
|
|
94
|
+
* @param rules - Ordered array of rules to evaluate.
|
|
95
|
+
* @param request - The normalized `HttpRequest` to process.
|
|
96
|
+
* @returns A `BehaviorResult` — either `{ action: 'respond', response }` or
|
|
97
|
+
* `{ action: 'continue', request }` with the final mutated request.
|
|
98
|
+
*/
|
|
99
|
+
declare function runRules(rules: Rule[], request: HttpRequest): BehaviorResult;
|
|
100
|
+
|
|
101
|
+
export { all, any, chain, not, rule, runRules };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { CriteriaFn, BehaviorFn, Rule, HttpRequest, BehaviorResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a rule that always runs the given behavior (no criteria guard).
|
|
5
|
+
*
|
|
6
|
+
* @param behavior - The behavior function to execute for every request.
|
|
7
|
+
* @returns A `Rule` object to pass to `defineViewerRequest`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Always set security headers, regardless of path
|
|
12
|
+
* rule(setSecurityHeaders())
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function rule(behavior: BehaviorFn): Rule;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a rule that runs the behavior only when the criteria returns `true`.
|
|
18
|
+
*
|
|
19
|
+
* @param criteria - Guard function; the behavior runs only when this returns `true`.
|
|
20
|
+
* @param behavior - The behavior function to execute when criteria matches.
|
|
21
|
+
* @returns A `Rule` object to pass to `defineViewerRequest`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* // Redirect /old-path to /new-path
|
|
26
|
+
* rule(pathPrefix(['/old-path']), redirect(301, '/new-path'))
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function rule(criteria: CriteriaFn, behavior: BehaviorFn): Rule;
|
|
30
|
+
/**
|
|
31
|
+
* Combines multiple criteria with AND logic — all must return `true`.
|
|
32
|
+
*
|
|
33
|
+
* @param fns - Array of criteria functions to evaluate.
|
|
34
|
+
* @returns A `CriteriaFn` that returns `true` only when every function in `fns` returns `true`.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* rule(all([pathPrefix(['/api/']), methodIs(['POST'])]), constructResponse({ statusCode: 403 }))
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare function all(fns: CriteriaFn[]): CriteriaFn;
|
|
42
|
+
/**
|
|
43
|
+
* Combines multiple criteria with OR logic — at least one must return `true`.
|
|
44
|
+
*
|
|
45
|
+
* @param fns - Array of criteria functions to evaluate.
|
|
46
|
+
* @returns A `CriteriaFn` that returns `true` when any function in `fns` returns `true`.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* rule(any([pathPrefix(['/admin/']), ipCidr(['10.0.0.0/8'])]), redirect(302, '/blocked'))
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare function any(fns: CriteriaFn[]): CriteriaFn;
|
|
54
|
+
/**
|
|
55
|
+
* Negates a criteria function — returns `true` when the wrapped function returns `false`.
|
|
56
|
+
*
|
|
57
|
+
* @param fn - The criteria function to negate.
|
|
58
|
+
* @returns A `CriteriaFn` that returns the logical inverse of `fn`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* // Block all non-internal IPs
|
|
63
|
+
* rule(not(ipCidr(['10.0.0.0/8', '192.168.0.0/16'])), redirect(302, '/blocked'))
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function not(fn: CriteriaFn): CriteriaFn;
|
|
67
|
+
/**
|
|
68
|
+
* Chains multiple behavior functions sequentially, passing the mutated request
|
|
69
|
+
* from each behavior to the next. Stops immediately if any behavior returns
|
|
70
|
+
* `{ action: 'respond' }`.
|
|
71
|
+
*
|
|
72
|
+
* Use this when a single Akamai rule has multiple behaviors that must operate
|
|
73
|
+
* on the same (possibly mutated) request. Without chaining, splitting behaviors
|
|
74
|
+
* into separate `rule()` calls causes each to re-evaluate criteria against
|
|
75
|
+
* the original request — breaking cases where behavior 1 rewrites the URI
|
|
76
|
+
* and behavior 2 must see the rewritten path.
|
|
77
|
+
*
|
|
78
|
+
* @param behaviors - Ordered array of behavior functions to execute in sequence.
|
|
79
|
+
* @returns A single `BehaviorFn` that runs all behaviors in order.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* rule(pathPrefix(['/api/']), chain([rewriteUri('replace', '/v2', '/api'), setRequestHeader('x-api-version', '2')]))
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare function chain(behaviors: BehaviorFn[]): BehaviorFn;
|
|
87
|
+
/**
|
|
88
|
+
* Executes an ordered list of rules against a request, stopping at the first
|
|
89
|
+
* rule whose behavior returns `{ action: 'respond' }`.
|
|
90
|
+
*
|
|
91
|
+
* This is called internally by `defineViewerRequest`; you rarely need to call
|
|
92
|
+
* it directly unless building a custom adapter.
|
|
93
|
+
*
|
|
94
|
+
* @param rules - Ordered array of rules to evaluate.
|
|
95
|
+
* @param request - The normalized `HttpRequest` to process.
|
|
96
|
+
* @returns A `BehaviorResult` — either `{ action: 'respond', response }` or
|
|
97
|
+
* `{ action: 'continue', request }` with the final mutated request.
|
|
98
|
+
*/
|
|
99
|
+
declare function runRules(rules: Rule[], request: HttpRequest): BehaviorResult;
|
|
100
|
+
|
|
101
|
+
export { all, any, chain, not, rule, runRules };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";require('../chunk-MEHWLQLR.cjs');
|