@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,28 @@
|
|
|
1
|
+
import { ResponseBehaviorFn } from '../core/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sets a response header to the specified value.
|
|
5
|
+
*
|
|
6
|
+
* Overwrites the header if it already exists. Header names are automatically
|
|
7
|
+
* lowercased to match CloudFront's normalized format.
|
|
8
|
+
*
|
|
9
|
+
* Use inside `defineViewerResponse` to add or override outgoing response headers.
|
|
10
|
+
*
|
|
11
|
+
* @param headerName - The response header name to set (e.g. `'x-custom-header'`). Case-insensitive.
|
|
12
|
+
* @param value - The value to assign to the header.
|
|
13
|
+
* @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { setResponseHeader } from '@viverse/cf-engine/behaviors'
|
|
18
|
+
* import { defineViewerResponse } from '@viverse/cf-engine/adapters/cf-function'
|
|
19
|
+
*
|
|
20
|
+
* export default defineViewerResponse([
|
|
21
|
+
* setResponseHeader('x-powered-by', 'CloudFront'),
|
|
22
|
+
* setResponseHeader('x-custom-env', 'production'),
|
|
23
|
+
* ])
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare function setResponseHeader(headerName: string, value: string): ResponseBehaviorFn;
|
|
27
|
+
|
|
28
|
+
export { setResponseHeader };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ResponseBehaviorFn } from '../core/types.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options for overriding individual security header values.
|
|
5
|
+
* All fields are optional; omitted fields fall back to their secure defaults.
|
|
6
|
+
*/
|
|
7
|
+
interface SecurityHeadersOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Value for the `Strict-Transport-Security` header.
|
|
10
|
+
* Default: `'max-age=31536000; includeSubDomains'`
|
|
11
|
+
*/
|
|
12
|
+
hsts?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Value for the `X-Frame-Options` header. Controls whether the page can be
|
|
15
|
+
* embedded in an iframe. Common values: `'DENY'`, `'SAMEORIGIN'`.
|
|
16
|
+
* Default: `'SAMEORIGIN'`
|
|
17
|
+
*/
|
|
18
|
+
xFrameOptions?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Value for the `X-Content-Type-Options` header. Set to `'nosniff'` to
|
|
21
|
+
* prevent browsers from MIME-sniffing the response content type.
|
|
22
|
+
* Default: `'nosniff'`
|
|
23
|
+
*/
|
|
24
|
+
xContentTypeOptions?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Sets common security headers on the outgoing response.
|
|
28
|
+
*
|
|
29
|
+
* Applied headers and their defaults:
|
|
30
|
+
* - `Strict-Transport-Security`: `max-age=31536000; includeSubDomains`
|
|
31
|
+
* - `X-Frame-Options`: `SAMEORIGIN`
|
|
32
|
+
* - `X-Content-Type-Options`: `nosniff`
|
|
33
|
+
*
|
|
34
|
+
* Akamai equivalent: `httpStrictTransportSecurity` behavior (HSTS only).
|
|
35
|
+
*
|
|
36
|
+
* @param options - Optional overrides for individual header values.
|
|
37
|
+
* @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* import { setSecurityHeaders } from '@viverse/cf-engine/behaviors'
|
|
42
|
+
* import { defineViewerResponse } from '@viverse/cf-engine/adapters/cf-function'
|
|
43
|
+
*
|
|
44
|
+
* // Apply defaults
|
|
45
|
+
* export default defineViewerResponse([setSecurityHeaders()])
|
|
46
|
+
*
|
|
47
|
+
* // Override HSTS and frame options
|
|
48
|
+
* export default defineViewerResponse([
|
|
49
|
+
* setSecurityHeaders({ hsts: 'max-age=63072000; includeSubDomains; preload', xFrameOptions: 'DENY' }),
|
|
50
|
+
* ])
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare function setSecurityHeaders(options?: SecurityHeadersOptions): ResponseBehaviorFn;
|
|
54
|
+
|
|
55
|
+
export { type SecurityHeadersOptions, setSecurityHeaders };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ResponseBehaviorFn } from '../core/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options for overriding individual security header values.
|
|
5
|
+
* All fields are optional; omitted fields fall back to their secure defaults.
|
|
6
|
+
*/
|
|
7
|
+
interface SecurityHeadersOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Value for the `Strict-Transport-Security` header.
|
|
10
|
+
* Default: `'max-age=31536000; includeSubDomains'`
|
|
11
|
+
*/
|
|
12
|
+
hsts?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Value for the `X-Frame-Options` header. Controls whether the page can be
|
|
15
|
+
* embedded in an iframe. Common values: `'DENY'`, `'SAMEORIGIN'`.
|
|
16
|
+
* Default: `'SAMEORIGIN'`
|
|
17
|
+
*/
|
|
18
|
+
xFrameOptions?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Value for the `X-Content-Type-Options` header. Set to `'nosniff'` to
|
|
21
|
+
* prevent browsers from MIME-sniffing the response content type.
|
|
22
|
+
* Default: `'nosniff'`
|
|
23
|
+
*/
|
|
24
|
+
xContentTypeOptions?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Sets common security headers on the outgoing response.
|
|
28
|
+
*
|
|
29
|
+
* Applied headers and their defaults:
|
|
30
|
+
* - `Strict-Transport-Security`: `max-age=31536000; includeSubDomains`
|
|
31
|
+
* - `X-Frame-Options`: `SAMEORIGIN`
|
|
32
|
+
* - `X-Content-Type-Options`: `nosniff`
|
|
33
|
+
*
|
|
34
|
+
* Akamai equivalent: `httpStrictTransportSecurity` behavior (HSTS only).
|
|
35
|
+
*
|
|
36
|
+
* @param options - Optional overrides for individual header values.
|
|
37
|
+
* @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* import { setSecurityHeaders } from '@viverse/cf-engine/behaviors'
|
|
42
|
+
* import { defineViewerResponse } from '@viverse/cf-engine/adapters/cf-function'
|
|
43
|
+
*
|
|
44
|
+
* // Apply defaults
|
|
45
|
+
* export default defineViewerResponse([setSecurityHeaders()])
|
|
46
|
+
*
|
|
47
|
+
* // Override HSTS and frame options
|
|
48
|
+
* export default defineViewerResponse([
|
|
49
|
+
* setSecurityHeaders({ hsts: 'max-age=63072000; includeSubDomains; preload', xFrameOptions: 'DENY' }),
|
|
50
|
+
* ])
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare function setSecurityHeaders(options?: SecurityHeadersOptions): ResponseBehaviorFn;
|
|
54
|
+
|
|
55
|
+
export { type SecurityHeadersOptions, setSecurityHeaders };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BehaviorFn } from '../core/types.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Removes specific query string parameters from the request before it is forwarded to the origin.
|
|
5
|
+
*
|
|
6
|
+
* Commonly used after `verifyToken` to strip the auth token query param so it
|
|
7
|
+
* is not exposed to the origin server.
|
|
8
|
+
*
|
|
9
|
+
* Parameters not present in the request are silently ignored.
|
|
10
|
+
*
|
|
11
|
+
* @param params - Array of query string parameter names to remove (case-sensitive).
|
|
12
|
+
* @returns A `BehaviorFn` to use as the second argument to `rule()`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { stripQueryParams, verifyToken } from '@viverse/cf-engine/behaviors'
|
|
17
|
+
* import { rule } from '@viverse/cf-engine'
|
|
18
|
+
*
|
|
19
|
+
* rule(verifyToken({ key: process.env.EDGE_AUTH_KEY! })),
|
|
20
|
+
* rule(stripQueryParams(['hdnts', 'imformat']))
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function stripQueryParams(params: string[]): BehaviorFn;
|
|
24
|
+
|
|
25
|
+
export { stripQueryParams };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BehaviorFn } from '../core/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Removes specific query string parameters from the request before it is forwarded to the origin.
|
|
5
|
+
*
|
|
6
|
+
* Commonly used after `verifyToken` to strip the auth token query param so it
|
|
7
|
+
* is not exposed to the origin server.
|
|
8
|
+
*
|
|
9
|
+
* Parameters not present in the request are silently ignored.
|
|
10
|
+
*
|
|
11
|
+
* @param params - Array of query string parameter names to remove (case-sensitive).
|
|
12
|
+
* @returns A `BehaviorFn` to use as the second argument to `rule()`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { stripQueryParams, verifyToken } from '@viverse/cf-engine/behaviors'
|
|
17
|
+
* import { rule } from '@viverse/cf-engine'
|
|
18
|
+
*
|
|
19
|
+
* rule(verifyToken({ key: process.env.EDGE_AUTH_KEY! })),
|
|
20
|
+
* rule(stripQueryParams(['hdnts', 'imformat']))
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function stripQueryParams(params: string[]): BehaviorFn;
|
|
24
|
+
|
|
25
|
+
export { stripQueryParams };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Rule, ResponseBehaviorFn, ResponseRule } from './core/types.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a CloudFront Function viewer-request handler from an ordered list of rules.
|
|
5
|
+
*
|
|
6
|
+
* The returned function is the CloudFront Function entry point. Assign it as
|
|
7
|
+
* `export default` or `var handler` depending on your runtime configuration.
|
|
8
|
+
*
|
|
9
|
+
* Rules are evaluated in order. Processing stops at the first rule whose behavior
|
|
10
|
+
* returns a response (e.g. `redirect`, `constructResponse`). If all rules continue,
|
|
11
|
+
* the (possibly mutated) request is forwarded to the origin.
|
|
12
|
+
*
|
|
13
|
+
* @param rules - Ordered array of `Rule` objects created with `rule()`.
|
|
14
|
+
* @returns A CloudFront Function handler `(event) => request | response`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { rule, not } from '@viverse/cf-engine'
|
|
19
|
+
* import { ipCidr, pathPrefix } from '@viverse/cf-engine/criteria'
|
|
20
|
+
* import { redirect, setRequestHeader } from '@viverse/cf-engine/behaviors'
|
|
21
|
+
* import { defineViewerRequest } from '@viverse/cf-engine/adapters/cf-function'
|
|
22
|
+
*
|
|
23
|
+
* export default defineViewerRequest([
|
|
24
|
+
* rule(not(ipCidr(['10.0.0.0/8'])), redirect(302, 'https://www.viverse.com')),
|
|
25
|
+
* rule(pathPrefix(['/api/']), setRequestHeader('x-forwarded-host', 'api.internal')),
|
|
26
|
+
* ])
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function defineViewerRequest(rules: Rule[]): (event: unknown) => unknown;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a CloudFront Function viewer-response handler from an ordered list of
|
|
32
|
+
* response behaviors or response rules.
|
|
33
|
+
*
|
|
34
|
+
* Each entry can be either:
|
|
35
|
+
* - A bare `ResponseBehaviorFn` — runs unconditionally on every response.
|
|
36
|
+
* - A `ResponseRule` `{ criteria, behavior }` — runs only when `criteria` returns `true`
|
|
37
|
+
* for the current request.
|
|
38
|
+
*
|
|
39
|
+
* All behaviors are applied in order; none can short-circuit the response.
|
|
40
|
+
* The final merged response object is returned to CloudFront.
|
|
41
|
+
*
|
|
42
|
+
* Note: If no behavior explicitly sets a body, the `body` field is omitted from
|
|
43
|
+
* the returned response to avoid overwriting the origin's actual content.
|
|
44
|
+
*
|
|
45
|
+
* @param responseBehaviors - Ordered array of `ResponseBehaviorFn` functions or
|
|
46
|
+
* `ResponseRule` objects `{ criteria?, behavior }`.
|
|
47
|
+
* @returns A CloudFront Function handler `(event) => response`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { setSecurityHeaders, setCorsHeaders, setResponseHeader } from '@viverse/cf-engine/behaviors'
|
|
52
|
+
* import { pathPrefix } from '@viverse/cf-engine/criteria'
|
|
53
|
+
* import { defineViewerResponse } from '@viverse/cf-engine/adapters/cf-function'
|
|
54
|
+
*
|
|
55
|
+
* export default defineViewerResponse([
|
|
56
|
+
* setSecurityHeaders(),
|
|
57
|
+
* setCorsHeaders({ allowedOrigins: ['https://www.viverse.com'] }),
|
|
58
|
+
* { criteria: pathPrefix(['/api/']), behavior: setResponseHeader('cache-control', 'no-store') },
|
|
59
|
+
* ])
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function defineViewerResponse(responseBehaviors: Array<ResponseBehaviorFn | ResponseRule>): (event: unknown) => unknown;
|
|
63
|
+
|
|
64
|
+
declare const cfFunction_defineViewerRequest: typeof defineViewerRequest;
|
|
65
|
+
declare const cfFunction_defineViewerResponse: typeof defineViewerResponse;
|
|
66
|
+
declare namespace cfFunction {
|
|
67
|
+
export { cfFunction_defineViewerRequest as defineViewerRequest, cfFunction_defineViewerResponse as defineViewerResponse };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { defineViewerResponse as a, cfFunction as c, defineViewerRequest as d };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Rule, ResponseBehaviorFn, ResponseRule } from './core/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a CloudFront Function viewer-request handler from an ordered list of rules.
|
|
5
|
+
*
|
|
6
|
+
* The returned function is the CloudFront Function entry point. Assign it as
|
|
7
|
+
* `export default` or `var handler` depending on your runtime configuration.
|
|
8
|
+
*
|
|
9
|
+
* Rules are evaluated in order. Processing stops at the first rule whose behavior
|
|
10
|
+
* returns a response (e.g. `redirect`, `constructResponse`). If all rules continue,
|
|
11
|
+
* the (possibly mutated) request is forwarded to the origin.
|
|
12
|
+
*
|
|
13
|
+
* @param rules - Ordered array of `Rule` objects created with `rule()`.
|
|
14
|
+
* @returns A CloudFront Function handler `(event) => request | response`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { rule, not } from '@viverse/cf-engine'
|
|
19
|
+
* import { ipCidr, pathPrefix } from '@viverse/cf-engine/criteria'
|
|
20
|
+
* import { redirect, setRequestHeader } from '@viverse/cf-engine/behaviors'
|
|
21
|
+
* import { defineViewerRequest } from '@viverse/cf-engine/adapters/cf-function'
|
|
22
|
+
*
|
|
23
|
+
* export default defineViewerRequest([
|
|
24
|
+
* rule(not(ipCidr(['10.0.0.0/8'])), redirect(302, 'https://www.viverse.com')),
|
|
25
|
+
* rule(pathPrefix(['/api/']), setRequestHeader('x-forwarded-host', 'api.internal')),
|
|
26
|
+
* ])
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function defineViewerRequest(rules: Rule[]): (event: unknown) => unknown;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a CloudFront Function viewer-response handler from an ordered list of
|
|
32
|
+
* response behaviors or response rules.
|
|
33
|
+
*
|
|
34
|
+
* Each entry can be either:
|
|
35
|
+
* - A bare `ResponseBehaviorFn` — runs unconditionally on every response.
|
|
36
|
+
* - A `ResponseRule` `{ criteria, behavior }` — runs only when `criteria` returns `true`
|
|
37
|
+
* for the current request.
|
|
38
|
+
*
|
|
39
|
+
* All behaviors are applied in order; none can short-circuit the response.
|
|
40
|
+
* The final merged response object is returned to CloudFront.
|
|
41
|
+
*
|
|
42
|
+
* Note: If no behavior explicitly sets a body, the `body` field is omitted from
|
|
43
|
+
* the returned response to avoid overwriting the origin's actual content.
|
|
44
|
+
*
|
|
45
|
+
* @param responseBehaviors - Ordered array of `ResponseBehaviorFn` functions or
|
|
46
|
+
* `ResponseRule` objects `{ criteria?, behavior }`.
|
|
47
|
+
* @returns A CloudFront Function handler `(event) => response`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { setSecurityHeaders, setCorsHeaders, setResponseHeader } from '@viverse/cf-engine/behaviors'
|
|
52
|
+
* import { pathPrefix } from '@viverse/cf-engine/criteria'
|
|
53
|
+
* import { defineViewerResponse } from '@viverse/cf-engine/adapters/cf-function'
|
|
54
|
+
*
|
|
55
|
+
* export default defineViewerResponse([
|
|
56
|
+
* setSecurityHeaders(),
|
|
57
|
+
* setCorsHeaders({ allowedOrigins: ['https://www.viverse.com'] }),
|
|
58
|
+
* { criteria: pathPrefix(['/api/']), behavior: setResponseHeader('cache-control', 'no-store') },
|
|
59
|
+
* ])
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function defineViewerResponse(responseBehaviors: Array<ResponseBehaviorFn | ResponseRule>): (event: unknown) => unknown;
|
|
63
|
+
|
|
64
|
+
declare const cfFunction_defineViewerRequest: typeof defineViewerRequest;
|
|
65
|
+
declare const cfFunction_defineViewerResponse: typeof defineViewerResponse;
|
|
66
|
+
declare namespace cfFunction {
|
|
67
|
+
export { cfFunction_defineViewerRequest as defineViewerRequest, cfFunction_defineViewerResponse as defineViewerResponse };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { defineViewerResponse as a, cfFunction as c, defineViewerRequest as d };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/shared/wildcard.ts
|
|
2
|
+
var regexCache = /* @__PURE__ */ Object.create(null);
|
|
3
|
+
function wildcardToRegex(pattern) {
|
|
4
|
+
if (!(pattern in regexCache)) {
|
|
5
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
6
|
+
regexCache[pattern] = new RegExp(`^${escaped}$`, "i");
|
|
7
|
+
}
|
|
8
|
+
return regexCache[pattern];
|
|
9
|
+
}
|
|
10
|
+
function matchesWildcard(str, pattern) {
|
|
11
|
+
return wildcardToRegex(pattern).test(str);
|
|
12
|
+
}
|
|
13
|
+
function matchesAnyWildcard(str, patterns) {
|
|
14
|
+
return patterns.some((p) => matchesWildcard(str, p));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
wildcardToRegex,
|
|
19
|
+
matchesWildcard,
|
|
20
|
+
matchesAnyWildcard
|
|
21
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
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/criteria/header-contains.ts
|
|
2
|
+
function headerContains(headerName, substrings) {
|
|
3
|
+
return (req) => {
|
|
4
|
+
const val = _optionalChain([req, 'access', _ => _.headers, 'access', _2 => _2[headerName.toLowerCase()], 'optionalAccess', _3 => _3.value]);
|
|
5
|
+
if (val === void 0) return false;
|
|
6
|
+
const lower = val.toLowerCase();
|
|
7
|
+
return substrings.some((s) => lower.includes(s.toLowerCase()));
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
exports.headerContains = headerContains;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
|
+
|
|
3
|
+
var _chunkWKYMSRCDcjs = require('./chunk-WKYMSRCD.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunk75ZPJI57cjs = require('./chunk-75ZPJI57.cjs');
|
|
7
|
+
|
|
8
|
+
// src/adapters/lambda-edge.ts
|
|
9
|
+
var lambda_edge_exports = {};
|
|
10
|
+
_chunk75ZPJI57cjs.__export.call(void 0, lambda_edge_exports, {
|
|
11
|
+
defineViewerRequest: () => defineViewerRequest,
|
|
12
|
+
defineViewerResponse: () => defineViewerResponse
|
|
13
|
+
});
|
|
14
|
+
function normalizeHeaders(headers) {
|
|
15
|
+
const result = {};
|
|
16
|
+
const entries = Object.entries(_nullishCoalesce(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(_nullishCoalesce(lambdaReq.querystring, () => ( ""))),
|
|
66
|
+
headers: normalizeHeaders(
|
|
67
|
+
_nullishCoalesce(lambdaReq.headers, () => ( {}))
|
|
68
|
+
),
|
|
69
|
+
clientIp: _nullishCoalesce(lambdaReq.clientIp, () => ( ""))
|
|
70
|
+
};
|
|
71
|
+
const result = _chunkWKYMSRCDcjs.runRules.call(void 0, 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: _nullishCoalesce(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(_nullishCoalesce(lambdaReq.querystring, () => ( ""))),
|
|
99
|
+
headers: normalizeHeaders(
|
|
100
|
+
_nullishCoalesce(lambdaReq.headers, () => ( {}))
|
|
101
|
+
),
|
|
102
|
+
clientIp: _nullishCoalesce(lambdaReq.clientIp, () => ( ""))
|
|
103
|
+
};
|
|
104
|
+
let response = {
|
|
105
|
+
statusCode: parseInt(lambdaRes.status, 10),
|
|
106
|
+
statusDescription: lambdaRes.statusDescription,
|
|
107
|
+
headers: normalizeHeaders(
|
|
108
|
+
_nullishCoalesce(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
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
exports.defineViewerRequest = defineViewerRequest; exports.defineViewerResponse = defineViewerResponse; exports.lambda_edge_exports = lambda_edge_exports;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/criteria/hostname-is.ts
|
|
2
|
+
function hostnameIs(hostnames) {
|
|
3
|
+
return (req) => {
|
|
4
|
+
const host = req.headers["host"]?.value?.toLowerCase();
|
|
5
|
+
if (!host) return false;
|
|
6
|
+
return hostnames.some((h) => h.toLowerCase() === host);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
hostnameIs
|
|
12
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/criteria/country-is.ts
|
|
2
|
+
function countryIs(codes) {
|
|
3
|
+
return (req) => {
|
|
4
|
+
const country = req.headers["cloudfront-viewer-country"]?.value?.toUpperCase();
|
|
5
|
+
if (!country) return false;
|
|
6
|
+
return codes.some((c) => c.toUpperCase() === country);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
countryIs
|
|
12
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/behaviors/image-optimize.ts
|
|
2
|
+
function selectBreakpoint(width, breakpoints) {
|
|
3
|
+
const sorted = breakpoints.slice().sort(function(a, b) {
|
|
4
|
+
return a - b;
|
|
5
|
+
});
|
|
6
|
+
for (var i = 0; i < sorted.length; i++) {
|
|
7
|
+
if (sorted[i] >= width) return sorted[i];
|
|
8
|
+
}
|
|
9
|
+
return sorted[sorted.length - 1];
|
|
10
|
+
}
|
|
11
|
+
function mapAkamaiFormat(akamaiFormat) {
|
|
12
|
+
switch (akamaiFormat) {
|
|
13
|
+
case "chrome":
|
|
14
|
+
case "webp":
|
|
15
|
+
return "webp";
|
|
16
|
+
case "avif":
|
|
17
|
+
return "avif";
|
|
18
|
+
default:
|
|
19
|
+
return "jpeg";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function selectFormat(acceptHeader, formats) {
|
|
23
|
+
if (acceptHeader) {
|
|
24
|
+
for (var i = 0; i < formats.length; i++) {
|
|
25
|
+
if (formats[i] === "avif" && acceptHeader.indexOf("image/avif") !== -1) return "avif";
|
|
26
|
+
if (formats[i] === "webp" && acceptHeader.indexOf("image/webp") !== -1) return "webp";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return formats[formats.length - 1] !== void 0 ? formats[formats.length - 1] : "jpeg";
|
|
30
|
+
}
|
|
31
|
+
function resolveImageParams(request, options) {
|
|
32
|
+
var formats = options.formats !== void 0 ? options.formats : ["avif", "webp", "jpeg"];
|
|
33
|
+
var quality = options.quality !== void 0 ? options.quality : 75;
|
|
34
|
+
var sortedBreakpoints = options.breakpoints.slice().sort(function(a, b) {
|
|
35
|
+
return a - b;
|
|
36
|
+
});
|
|
37
|
+
var imwidthParamName = options.imwidthParam !== void 0 ? options.imwidthParam : "imwidth";
|
|
38
|
+
var imformatParamName = options.imformatParam !== void 0 ? options.imformatParam : "imformat";
|
|
39
|
+
var width = NaN;
|
|
40
|
+
var imwidthVal = request.querystring[imwidthParamName] !== void 0 ? request.querystring[imwidthParamName].value : void 0;
|
|
41
|
+
if (imwidthVal !== void 0) {
|
|
42
|
+
var parsed = parseInt(imwidthVal, 10);
|
|
43
|
+
if (isFinite(parsed)) width = parsed;
|
|
44
|
+
}
|
|
45
|
+
if (!isFinite(width)) {
|
|
46
|
+
var widthHeader = request.headers["cloudfront-viewer-width"] !== void 0 ? request.headers["cloudfront-viewer-width"].value : void 0;
|
|
47
|
+
if (widthHeader !== void 0) {
|
|
48
|
+
var parsedHeader = parseInt(widthHeader, 10);
|
|
49
|
+
if (isFinite(parsedHeader)) width = parsedHeader;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
var breakpoint = isFinite(width) ? selectBreakpoint(width, sortedBreakpoints) : sortedBreakpoints[sortedBreakpoints.length - 1];
|
|
53
|
+
var format;
|
|
54
|
+
var imformatVal = request.querystring[imformatParamName] !== void 0 ? request.querystring[imformatParamName].value : void 0;
|
|
55
|
+
if (imformatVal !== void 0) {
|
|
56
|
+
format = mapAkamaiFormat(imformatVal);
|
|
57
|
+
} else {
|
|
58
|
+
var acceptVal = request.headers["accept"] !== void 0 ? request.headers["accept"].value : void 0;
|
|
59
|
+
format = selectFormat(acceptVal, formats);
|
|
60
|
+
}
|
|
61
|
+
return { breakpoint, format, quality };
|
|
62
|
+
}
|
|
63
|
+
function imageOptimize(options) {
|
|
64
|
+
var imformatParamName = options.imformatParam !== void 0 ? options.imformatParam : "imformat";
|
|
65
|
+
return function(request) {
|
|
66
|
+
var resolved = resolveImageParams(request, options);
|
|
67
|
+
var qs = Object.assign({}, request.querystring);
|
|
68
|
+
qs["imwidth"] = { value: String(resolved.breakpoint) };
|
|
69
|
+
qs["f"] = { value: resolved.format };
|
|
70
|
+
if (qs["q"] === void 0) {
|
|
71
|
+
var legacyQuality = qs["quality"] !== void 0 ? qs["quality"].value : void 0;
|
|
72
|
+
qs["q"] = { value: legacyQuality !== void 0 ? legacyQuality : String(resolved.quality) };
|
|
73
|
+
}
|
|
74
|
+
delete qs["quality"];
|
|
75
|
+
delete qs[imformatParamName];
|
|
76
|
+
if (imformatParamName !== "imformat") {
|
|
77
|
+
delete qs["imformat"];
|
|
78
|
+
}
|
|
79
|
+
var headers = Object.assign({}, request.headers);
|
|
80
|
+
if (options.origin !== void 0) {
|
|
81
|
+
headers["x-img-source-type"] = { value: options.origin.type };
|
|
82
|
+
if (options.origin.type === "gateway") {
|
|
83
|
+
headers["x-img-upstream-gateway"] = { value: options.origin.upstreamGateway };
|
|
84
|
+
} else {
|
|
85
|
+
headers["x-img-source-bucket"] = { value: options.origin.sourceBucket };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (options.originSecret !== void 0) {
|
|
89
|
+
headers["x-origin-verify"] = { value: options.originSecret };
|
|
90
|
+
}
|
|
91
|
+
return { action: "continue", request: Object.assign({}, request, { querystring: qs, headers }) };
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
resolveImageParams,
|
|
97
|
+
imageOptimize
|
|
98
|
+
};
|