@rayselfs/cf-rule-engine 1.7.0 → 1.8.1
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 +31 -3
- package/dist/adapters/cf-function.cjs +4 -4
- package/dist/adapters/cf-function.js +3 -3
- package/dist/adapters/lambda-edge.d.cts +1 -1
- package/dist/adapters/lambda-edge.d.ts +1 -1
- package/dist/adapters/viewer-request.cjs +3 -3
- package/dist/adapters/viewer-request.js +2 -2
- package/dist/behaviors/index.cjs +13 -13
- package/dist/behaviors/index.js +12 -12
- package/dist/behaviors/set-cors-headers.cjs +6 -2
- package/dist/behaviors/set-cors-headers.d.cts +53 -42
- package/dist/behaviors/set-cors-headers.d.ts +53 -42
- package/dist/behaviors/set-cors-headers.js +5 -1
- package/dist/{chunk-H2LO6MQG.js → chunk-CLDF6FM5.js} +22 -12
- package/dist/{chunk-PR5UQJCC.js → chunk-MTZ35AIR.js} +1 -1
- package/dist/{chunk-SOBTD7AD.js → chunk-PI7RKMGS.js} +21 -10
- package/dist/{chunk-63WIEBQB.cjs → chunk-PW4FKMJ2.cjs} +22 -12
- package/dist/{chunk-5ZIB3AJ7.cjs → chunk-SYPOHDLN.cjs} +2 -2
- package/dist/chunk-XWJEVLMZ.cjs +50 -0
- package/dist/criteria/header-equals.d.cts +2 -2
- package/dist/criteria/header-equals.d.ts +2 -2
- package/dist/criteria/index.cjs +12 -12
- package/dist/criteria/index.js +12 -12
- package/dist/helpers/index.cjs +9 -8
- package/dist/helpers/index.js +8 -7
- package/dist/helpers/preflight-request.cjs +3 -2
- package/dist/helpers/preflight-request.d.cts +7 -6
- package/dist/helpers/preflight-request.d.ts +7 -6
- package/dist/helpers/preflight-request.js +2 -1
- package/dist/helpers/whitelist.cjs +3 -3
- package/dist/helpers/whitelist.js +2 -2
- package/dist/index.cjs +7 -7
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/{lambda-edge-9xiONGmR.d.cts → lambda-edge-D1NHYwvA.d.cts} +1 -1
- package/dist/{lambda-edge-BK3-bFx8.d.ts → lambda-edge-DnIvWFGe.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-GK5JX7OM.cjs +0 -39
- package/dist/{chunk-SGN2N3WI.cjs → chunk-FK3B4SP5.cjs} +2 -2
- package/dist/{chunk-BJZPAQHW.js → chunk-I2GJR6LY.js} +3 -3
- package/dist/{chunk-ER2YEZZO.js → chunk-RL7ZETZR.js} +3 -3
- package/dist/{chunk-MO7HW25R.cjs → chunk-T5EXFHVA.cjs} +3 -3
package/README.md
CHANGED
|
@@ -29,12 +29,12 @@ export default defineViewerRequest([
|
|
|
29
29
|
**viewer-response** — security and CORS headers:
|
|
30
30
|
|
|
31
31
|
```typescript
|
|
32
|
-
import { setSecurityHeaders, setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors/index'
|
|
32
|
+
import { setSecurityHeaders, setCorsHeaders, ORIGIN_WILDCARD } from '@rayselfs/cf-rule-engine/behaviors/index'
|
|
33
33
|
import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
|
|
34
34
|
|
|
35
35
|
export default defineViewerResponse([
|
|
36
36
|
setSecurityHeaders(),
|
|
37
|
-
setCorsHeaders({ allowedOrigins:
|
|
37
|
+
setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
|
|
38
38
|
])
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -113,6 +113,33 @@ Use `chain()` when one behavior must see the request mutations (URI rewrite, hea
|
|
|
113
113
|
| `imageOptimize(options)` | ✅ | ✅ |
|
|
114
114
|
| `verifyToken(options)` | ❌ | ✅ |
|
|
115
115
|
|
|
116
|
+
### setCorsHeaders — OriginPolicy
|
|
117
|
+
|
|
118
|
+
`allowedOrigins` accepts an `OriginPolicy` that controls how `Access-Control-Allow-Origin` is set:
|
|
119
|
+
|
|
120
|
+
| Value | Behavior |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `ORIGIN_WILDCARD` (`'*'`) | Static `Access-Control-Allow-Origin: *` — for fully public APIs |
|
|
123
|
+
| `Origin[]` | Compare request `Origin` against the list; echo if matched, skip if not. Supports wildcard subdomains (`https://*.example.com`). |
|
|
124
|
+
| `ORIGIN_ECHO` (`'echo'`) | Echo any request `Origin` if present, skip if none — use with `allowCredentials: true` |
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { setCorsHeaders, ORIGIN_WILDCARD, ORIGIN_ECHO } from '@rayselfs/cf-rule-engine/behaviors/index'
|
|
128
|
+
|
|
129
|
+
// Public API
|
|
130
|
+
setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD })
|
|
131
|
+
|
|
132
|
+
// Restricted — echo only listed origins
|
|
133
|
+
setCorsHeaders({ allowedOrigins: ['https://*.viverse.com', 'https://sdk-api.viverse.com'] })
|
|
134
|
+
|
|
135
|
+
// Echo any origin (required when allowCredentials: true)
|
|
136
|
+
setCorsHeaders({ allowedOrigins: ORIGIN_ECHO, allowCredentials: true })
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`allowedMethods` accepts a `Methods[]` array (e.g. `['GET', 'POST', 'OPTIONS']`); items are joined with `, ` to form the header value.
|
|
140
|
+
`allowedHeaders` accepts a `string[]` array (e.g. `['Content-Type', 'Authorization']`); items are joined with `, `.
|
|
141
|
+
Both are optional — omit to exclude those headers from the response.
|
|
142
|
+
|
|
116
143
|
## Helpers (`@rayselfs/cf-rule-engine/helpers/index`)
|
|
117
144
|
|
|
118
145
|
Helpers are pre-configured rule factories that combine multiple criteria and behaviors for common use cases.
|
|
@@ -134,9 +161,10 @@ Adds `x-cf-distribution: staging` to the response when the request carries `aws-
|
|
|
134
161
|
|
|
135
162
|
```typescript
|
|
136
163
|
import { stagingIndicator } from '@rayselfs/cf-rule-engine/helpers/index'
|
|
164
|
+
import { setCorsHeaders, ORIGIN_WILDCARD } from '@rayselfs/cf-rule-engine/behaviors/index'
|
|
137
165
|
|
|
138
166
|
defineViewerResponse([
|
|
139
|
-
setCorsHeaders({ allowedOrigins:
|
|
167
|
+
setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
|
|
140
168
|
stagingIndicator(),
|
|
141
169
|
])
|
|
142
170
|
```
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-SYPOHDLN.cjs');
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-WKYMSRCD.cjs');
|
|
4
|
+
var _chunkFK3B4SP5cjs = require('../chunk-FK3B4SP5.cjs');
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
var _chunkN6QAQALUcjs = require('../chunk-N6QAQALU.cjs');
|
|
9
8
|
require('../chunk-6NFAPLQ7.cjs');
|
|
9
|
+
require('../chunk-WKYMSRCD.cjs');
|
|
10
10
|
require('../chunk-75ZPJI57.cjs');
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
exports.defineViewerRequest =
|
|
14
|
+
exports.defineViewerRequest = _chunkFK3B4SP5cjs.defineViewerRequest; exports.defineViewerResponse = _chunkN6QAQALUcjs.defineViewerResponse;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-MTZ35AIR.js";
|
|
2
2
|
import {
|
|
3
3
|
defineViewerRequest
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-Q4NP4C3B.js";
|
|
4
|
+
} from "../chunk-I2GJR6LY.js";
|
|
6
5
|
import {
|
|
7
6
|
defineViewerResponse
|
|
8
7
|
} from "../chunk-TURH5IFN.js";
|
|
9
8
|
import "../chunk-CQ7YZ3AR.js";
|
|
9
|
+
import "../chunk-Q4NP4C3B.js";
|
|
10
10
|
import "../chunk-MLKGABMK.js";
|
|
11
11
|
export {
|
|
12
12
|
defineViewerRequest,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import '../core/types.cjs';
|
|
2
|
-
export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-
|
|
2
|
+
export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-D1NHYwvA.cjs';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import '../core/types.js';
|
|
2
|
-
export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-
|
|
2
|
+
export { d as defineViewerRequest, a as defineViewerResponse } from '../lambda-edge-DnIvWFGe.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-WKYMSRCD.cjs');
|
|
3
|
+
var _chunkFK3B4SP5cjs = require('../chunk-FK3B4SP5.cjs');
|
|
5
4
|
require('../chunk-6NFAPLQ7.cjs');
|
|
5
|
+
require('../chunk-WKYMSRCD.cjs');
|
|
6
6
|
require('../chunk-75ZPJI57.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
exports.defineViewerRequest =
|
|
9
|
+
exports.defineViewerRequest = _chunkFK3B4SP5cjs.defineViewerRequest;
|
package/dist/behaviors/index.cjs
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }
|
|
2
2
|
|
|
3
|
+
var _chunkXWJEVLMZcjs = require('../chunk-XWJEVLMZ.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunkZXS23HXAcjs = require('../chunk-ZXS23HXA.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
3
9
|
var _chunkPPUHEL4Hcjs = require('../chunk-PPUHEL4H.cjs');
|
|
4
10
|
|
|
5
11
|
|
|
@@ -12,6 +18,12 @@ var _chunk3UXNXJ6Ncjs = require('../chunk-3UXNXJ6N.cjs');
|
|
|
12
18
|
var _chunkMSES76XKcjs = require('../chunk-MSES76XK.cjs');
|
|
13
19
|
|
|
14
20
|
|
|
21
|
+
var _chunkJU5WX5RUcjs = require('../chunk-JU5WX5RU.cjs');
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
var _chunkLTLBEBKLcjs = require('../chunk-LTLBEBKL.cjs');
|
|
25
|
+
|
|
26
|
+
|
|
15
27
|
var _chunkKXC6ES3Bcjs = require('../chunk-KXC6ES3B.cjs');
|
|
16
28
|
|
|
17
29
|
|
|
@@ -27,19 +39,7 @@ var _chunkMRPTC74Icjs = require('../chunk-MRPTC74I.cjs');
|
|
|
27
39
|
var _chunkCV234DQTcjs = require('../chunk-CV234DQT.cjs');
|
|
28
40
|
|
|
29
41
|
|
|
30
|
-
var _chunkGK5JX7OMcjs = require('../chunk-GK5JX7OM.cjs');
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
var _chunkZXS23HXAcjs = require('../chunk-ZXS23HXA.cjs');
|
|
34
|
-
|
|
35
|
-
|
|
36
42
|
var _chunkOSGZTNTScjs = require('../chunk-OSGZTNTS.cjs');
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var _chunkJU5WX5RUcjs = require('../chunk-JU5WX5RU.cjs');
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
var _chunkLTLBEBKLcjs = require('../chunk-LTLBEBKL.cjs');
|
|
43
43
|
require('../chunk-75ZPJI57.cjs');
|
|
44
44
|
|
|
45
45
|
// src/behaviors/verify-token.ts
|
|
@@ -123,4 +123,4 @@ function verifyToken(options) {
|
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
|
|
126
|
-
exports.constructResponse = _chunkOSGZTNTScjs.constructResponse; exports.copyHeader = _chunkJU5WX5RUcjs.copyHeader; exports.directoryIndex = _chunkLTLBEBKLcjs.directoryIndex; exports.imageOptimize = _chunkKXC6ES3Bcjs.imageOptimize; exports.redirect = _chunkWWSRNCUPcjs.redirect; exports.removeResponseHeaders = _chunkSGEBNQR2cjs.removeResponseHeaders; exports.rewriteUri = _chunkMRPTC74Icjs.rewriteUri; exports.setCacheControl = _chunkCV234DQTcjs.setCacheControl; exports.setCorsHeaders =
|
|
126
|
+
exports.constructResponse = _chunkOSGZTNTScjs.constructResponse; exports.copyHeader = _chunkJU5WX5RUcjs.copyHeader; exports.directoryIndex = _chunkLTLBEBKLcjs.directoryIndex; exports.imageOptimize = _chunkKXC6ES3Bcjs.imageOptimize; exports.redirect = _chunkWWSRNCUPcjs.redirect; exports.removeResponseHeaders = _chunkSGEBNQR2cjs.removeResponseHeaders; exports.rewriteUri = _chunkMRPTC74Icjs.rewriteUri; exports.setCacheControl = _chunkCV234DQTcjs.setCacheControl; exports.setCorsHeaders = _chunkXWJEVLMZcjs.setCorsHeaders; exports.setCsp = _chunkZXS23HXAcjs.setCsp; exports.setRequestHeader = _chunkPPUHEL4Hcjs.setRequestHeader; exports.setResponseHeader = _chunkB4WEJSEZcjs.setResponseHeader; exports.setSecurityHeaders = _chunk3UXNXJ6Ncjs.setSecurityHeaders; exports.stripQueryParams = _chunkMSES76XKcjs.stripQueryParams; exports.verifyToken = verifyToken;
|
package/dist/behaviors/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
setCorsHeaders
|
|
3
|
+
} from "../chunk-PI7RKMGS.js";
|
|
4
|
+
import {
|
|
5
|
+
setCsp
|
|
6
|
+
} from "../chunk-XUI4Y22M.js";
|
|
1
7
|
import {
|
|
2
8
|
setRequestHeader
|
|
3
9
|
} from "../chunk-M5KUQBDW.js";
|
|
@@ -10,6 +16,12 @@ import {
|
|
|
10
16
|
import {
|
|
11
17
|
stripQueryParams
|
|
12
18
|
} from "../chunk-XPQG5IML.js";
|
|
19
|
+
import {
|
|
20
|
+
copyHeader
|
|
21
|
+
} from "../chunk-BDNPQ7AU.js";
|
|
22
|
+
import {
|
|
23
|
+
directoryIndex
|
|
24
|
+
} from "../chunk-R7WXS7BI.js";
|
|
13
25
|
import {
|
|
14
26
|
imageOptimize
|
|
15
27
|
} from "../chunk-LQRLWDQQ.js";
|
|
@@ -25,21 +37,9 @@ import {
|
|
|
25
37
|
import {
|
|
26
38
|
setCacheControl
|
|
27
39
|
} from "../chunk-ZTMSH34E.js";
|
|
28
|
-
import {
|
|
29
|
-
setCorsHeaders
|
|
30
|
-
} from "../chunk-SOBTD7AD.js";
|
|
31
|
-
import {
|
|
32
|
-
setCsp
|
|
33
|
-
} from "../chunk-XUI4Y22M.js";
|
|
34
40
|
import {
|
|
35
41
|
constructResponse
|
|
36
42
|
} from "../chunk-6DBZBV2M.js";
|
|
37
|
-
import {
|
|
38
|
-
copyHeader
|
|
39
|
-
} from "../chunk-BDNPQ7AU.js";
|
|
40
|
-
import {
|
|
41
|
-
directoryIndex
|
|
42
|
-
} from "../chunk-R7WXS7BI.js";
|
|
43
43
|
import "../chunk-MLKGABMK.js";
|
|
44
44
|
|
|
45
45
|
// src/behaviors/verify-token.ts
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkXWJEVLMZcjs = require('../chunk-XWJEVLMZ.cjs');
|
|
4
6
|
require('../chunk-75ZPJI57.cjs');
|
|
5
7
|
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
exports.ORIGIN_ECHO = _chunkXWJEVLMZcjs.ORIGIN_ECHO; exports.ORIGIN_WILDCARD = _chunkXWJEVLMZcjs.ORIGIN_WILDCARD; exports.setCorsHeaders = _chunkXWJEVLMZcjs.setCorsHeaders;
|
|
@@ -1,38 +1,52 @@
|
|
|
1
1
|
import { ResponseBehaviorFn } from '../core/types.cjs';
|
|
2
2
|
|
|
3
|
+
declare const ORIGIN_WILDCARD: "*";
|
|
4
|
+
type OriginWildcard = typeof ORIGIN_WILDCARD;
|
|
5
|
+
declare const ORIGIN_ECHO: "echo";
|
|
6
|
+
type OriginEcho = typeof ORIGIN_ECHO;
|
|
3
7
|
/**
|
|
4
|
-
*
|
|
8
|
+
* A valid HTTP origin — must start with `https://` or `http://`.
|
|
9
|
+
* Supports wildcard subdomains (e.g. `https://*.viverse.com`).
|
|
10
|
+
*/
|
|
11
|
+
type Origin = `https://${string}` | `http://${string}`;
|
|
12
|
+
/**
|
|
13
|
+
* Controls how `Access-Control-Allow-Origin` is set:
|
|
14
|
+
* - `ORIGIN_WILDCARD` (`'*'`) — static `*`, allows all origins without inspection
|
|
15
|
+
* - `Origin[]` — compare request `Origin` header against the list; echo if matched, skip if not
|
|
16
|
+
* - `ORIGIN_ECHO` (`'echo'`) — echo any request `Origin` if present, skip if none
|
|
17
|
+
*/
|
|
18
|
+
type OriginPolicy = OriginWildcard | Origin[] | OriginEcho;
|
|
19
|
+
/**
|
|
20
|
+
* Standard HTTP methods allowed in `Access-Control-Allow-Methods`.
|
|
21
|
+
*/
|
|
22
|
+
type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'TRACE' | 'CONNECT';
|
|
23
|
+
/**
|
|
24
|
+
* CORS configuration options for `setCorsHeaders` and `preflightRequest`.
|
|
5
25
|
*/
|
|
6
26
|
interface CorsOptions {
|
|
7
27
|
/**
|
|
8
|
-
*
|
|
9
|
-
* (e.g. `'https://*.example.com'`). Use `['*']` to allow all origins.
|
|
10
|
-
* Default: `['*']`
|
|
11
|
-
*/
|
|
12
|
-
allowedOrigins?: string[];
|
|
13
|
-
/**
|
|
14
|
-
* When `true`, reflects the incoming `Origin` request header as the
|
|
15
|
-
* `Access-Control-Allow-Origin` response value, provided it matches one of
|
|
16
|
-
* `allowedOrigins`. Required when `allowCredentials` is `true` (browsers reject
|
|
17
|
-
* `Access-Control-Allow-Origin: *` with credentials).
|
|
18
|
-
* Default: `false`
|
|
28
|
+
* Origin policy. See `OriginPolicy` for details.
|
|
19
29
|
*/
|
|
20
|
-
|
|
30
|
+
allowedOrigins: OriginPolicy;
|
|
21
31
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
32
|
+
* HTTP methods to include in `Access-Control-Allow-Methods`.
|
|
33
|
+
* Array items are joined with `, ` before being written to the header.
|
|
34
|
+
* Omit to exclude the header.
|
|
35
|
+
*
|
|
36
|
+
* @example `['GET', 'POST', 'OPTIONS']`
|
|
24
37
|
*/
|
|
25
|
-
allowedMethods?:
|
|
38
|
+
allowedMethods?: Methods[];
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
40
|
+
* Header names to include in `Access-Control-Allow-Headers`.
|
|
41
|
+
* Array items are joined with `, ` before being written to the header.
|
|
42
|
+
* Omit to exclude the header.
|
|
43
|
+
*
|
|
44
|
+
* @example `['Content-Type', 'Authorization']`
|
|
29
45
|
*/
|
|
30
|
-
allowedHeaders?: string;
|
|
46
|
+
allowedHeaders?: string[];
|
|
31
47
|
/**
|
|
32
48
|
* When `true`, sets `Access-Control-Allow-Credentials: true`.
|
|
33
|
-
*
|
|
34
|
-
* wildcard origins when credentials are present.
|
|
35
|
-
* Default: `false`
|
|
49
|
+
* Use with `ORIGIN_ECHO` or `Origin[]` — browsers reject `*` with credentials.
|
|
36
50
|
*/
|
|
37
51
|
allowCredentials?: boolean;
|
|
38
52
|
/**
|
|
@@ -42,35 +56,32 @@ interface CorsOptions {
|
|
|
42
56
|
maxAge?: number;
|
|
43
57
|
}
|
|
44
58
|
/**
|
|
45
|
-
* Sets CORS response headers with configurable origin
|
|
46
|
-
* credentials, and preflight cache duration.
|
|
59
|
+
* Sets CORS response headers with configurable origin policy.
|
|
47
60
|
*
|
|
48
|
-
*
|
|
49
|
-
* for each CORS header individually.
|
|
50
|
-
*
|
|
51
|
-
* @param options - CORS configuration. All fields are optional with safe defaults.
|
|
61
|
+
* @param options - CORS configuration. `allowedOrigins` is required.
|
|
52
62
|
* @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
|
|
53
63
|
*
|
|
54
64
|
* @example
|
|
55
65
|
* ```ts
|
|
56
|
-
* import { setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors'
|
|
57
|
-
* import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/
|
|
66
|
+
* import { setCorsHeaders, ORIGIN_WILDCARD, ORIGIN_ECHO } from '@rayselfs/cf-rule-engine/behaviors/set-cors-headers'
|
|
67
|
+
* import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
|
|
68
|
+
*
|
|
69
|
+
* // Public API — static Access-Control-Allow-Origin: *
|
|
70
|
+
* export default defineViewerResponse([
|
|
71
|
+
* setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
|
|
72
|
+
* ])
|
|
58
73
|
*
|
|
59
|
-
* //
|
|
60
|
-
* export default defineViewerResponse([
|
|
74
|
+
* // Restricted — echo only listed origins (supports wildcard subdomains)
|
|
75
|
+
* export default defineViewerResponse([
|
|
76
|
+
* setCorsHeaders({ allowedOrigins: ['https://*.viverse.com', 'https://sdk-api.viverse.com'] }),
|
|
77
|
+
* ])
|
|
61
78
|
*
|
|
62
|
-
* // Echo origin
|
|
79
|
+
* // Echo any origin (e.g. for credentialed requests)
|
|
63
80
|
* export default defineViewerResponse([
|
|
64
|
-
* setCorsHeaders({
|
|
65
|
-
* allowedOrigins: ['https://www.example.com', 'https://*.example.com'],
|
|
66
|
-
* allowOriginEcho: true,
|
|
67
|
-
* allowCredentials: true,
|
|
68
|
-
* allowedMethods: 'GET, POST, PUT, DELETE, OPTIONS',
|
|
69
|
-
* maxAge: 86400,
|
|
70
|
-
* }),
|
|
81
|
+
* setCorsHeaders({ allowedOrigins: ORIGIN_ECHO, allowCredentials: true }),
|
|
71
82
|
* ])
|
|
72
83
|
* ```
|
|
73
84
|
*/
|
|
74
|
-
declare function setCorsHeaders(options
|
|
85
|
+
declare function setCorsHeaders(options: CorsOptions): ResponseBehaviorFn;
|
|
75
86
|
|
|
76
|
-
export { type CorsOptions, setCorsHeaders };
|
|
87
|
+
export { type CorsOptions, type Methods, ORIGIN_ECHO, ORIGIN_WILDCARD, type Origin, type OriginEcho, type OriginPolicy, type OriginWildcard, setCorsHeaders };
|
|
@@ -1,38 +1,52 @@
|
|
|
1
1
|
import { ResponseBehaviorFn } from '../core/types.js';
|
|
2
2
|
|
|
3
|
+
declare const ORIGIN_WILDCARD: "*";
|
|
4
|
+
type OriginWildcard = typeof ORIGIN_WILDCARD;
|
|
5
|
+
declare const ORIGIN_ECHO: "echo";
|
|
6
|
+
type OriginEcho = typeof ORIGIN_ECHO;
|
|
3
7
|
/**
|
|
4
|
-
*
|
|
8
|
+
* A valid HTTP origin — must start with `https://` or `http://`.
|
|
9
|
+
* Supports wildcard subdomains (e.g. `https://*.viverse.com`).
|
|
10
|
+
*/
|
|
11
|
+
type Origin = `https://${string}` | `http://${string}`;
|
|
12
|
+
/**
|
|
13
|
+
* Controls how `Access-Control-Allow-Origin` is set:
|
|
14
|
+
* - `ORIGIN_WILDCARD` (`'*'`) — static `*`, allows all origins without inspection
|
|
15
|
+
* - `Origin[]` — compare request `Origin` header against the list; echo if matched, skip if not
|
|
16
|
+
* - `ORIGIN_ECHO` (`'echo'`) — echo any request `Origin` if present, skip if none
|
|
17
|
+
*/
|
|
18
|
+
type OriginPolicy = OriginWildcard | Origin[] | OriginEcho;
|
|
19
|
+
/**
|
|
20
|
+
* Standard HTTP methods allowed in `Access-Control-Allow-Methods`.
|
|
21
|
+
*/
|
|
22
|
+
type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'TRACE' | 'CONNECT';
|
|
23
|
+
/**
|
|
24
|
+
* CORS configuration options for `setCorsHeaders` and `preflightRequest`.
|
|
5
25
|
*/
|
|
6
26
|
interface CorsOptions {
|
|
7
27
|
/**
|
|
8
|
-
*
|
|
9
|
-
* (e.g. `'https://*.example.com'`). Use `['*']` to allow all origins.
|
|
10
|
-
* Default: `['*']`
|
|
11
|
-
*/
|
|
12
|
-
allowedOrigins?: string[];
|
|
13
|
-
/**
|
|
14
|
-
* When `true`, reflects the incoming `Origin` request header as the
|
|
15
|
-
* `Access-Control-Allow-Origin` response value, provided it matches one of
|
|
16
|
-
* `allowedOrigins`. Required when `allowCredentials` is `true` (browsers reject
|
|
17
|
-
* `Access-Control-Allow-Origin: *` with credentials).
|
|
18
|
-
* Default: `false`
|
|
28
|
+
* Origin policy. See `OriginPolicy` for details.
|
|
19
29
|
*/
|
|
20
|
-
|
|
30
|
+
allowedOrigins: OriginPolicy;
|
|
21
31
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
32
|
+
* HTTP methods to include in `Access-Control-Allow-Methods`.
|
|
33
|
+
* Array items are joined with `, ` before being written to the header.
|
|
34
|
+
* Omit to exclude the header.
|
|
35
|
+
*
|
|
36
|
+
* @example `['GET', 'POST', 'OPTIONS']`
|
|
24
37
|
*/
|
|
25
|
-
allowedMethods?:
|
|
38
|
+
allowedMethods?: Methods[];
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
40
|
+
* Header names to include in `Access-Control-Allow-Headers`.
|
|
41
|
+
* Array items are joined with `, ` before being written to the header.
|
|
42
|
+
* Omit to exclude the header.
|
|
43
|
+
*
|
|
44
|
+
* @example `['Content-Type', 'Authorization']`
|
|
29
45
|
*/
|
|
30
|
-
allowedHeaders?: string;
|
|
46
|
+
allowedHeaders?: string[];
|
|
31
47
|
/**
|
|
32
48
|
* When `true`, sets `Access-Control-Allow-Credentials: true`.
|
|
33
|
-
*
|
|
34
|
-
* wildcard origins when credentials are present.
|
|
35
|
-
* Default: `false`
|
|
49
|
+
* Use with `ORIGIN_ECHO` or `Origin[]` — browsers reject `*` with credentials.
|
|
36
50
|
*/
|
|
37
51
|
allowCredentials?: boolean;
|
|
38
52
|
/**
|
|
@@ -42,35 +56,32 @@ interface CorsOptions {
|
|
|
42
56
|
maxAge?: number;
|
|
43
57
|
}
|
|
44
58
|
/**
|
|
45
|
-
* Sets CORS response headers with configurable origin
|
|
46
|
-
* credentials, and preflight cache duration.
|
|
59
|
+
* Sets CORS response headers with configurable origin policy.
|
|
47
60
|
*
|
|
48
|
-
*
|
|
49
|
-
* for each CORS header individually.
|
|
50
|
-
*
|
|
51
|
-
* @param options - CORS configuration. All fields are optional with safe defaults.
|
|
61
|
+
* @param options - CORS configuration. `allowedOrigins` is required.
|
|
52
62
|
* @returns A `ResponseBehaviorFn` to use directly in `defineViewerResponse` or wrapped in a `ResponseRule`.
|
|
53
63
|
*
|
|
54
64
|
* @example
|
|
55
65
|
* ```ts
|
|
56
|
-
* import { setCorsHeaders } from '@rayselfs/cf-rule-engine/behaviors'
|
|
57
|
-
* import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/
|
|
66
|
+
* import { setCorsHeaders, ORIGIN_WILDCARD, ORIGIN_ECHO } from '@rayselfs/cf-rule-engine/behaviors/set-cors-headers'
|
|
67
|
+
* import { defineViewerResponse } from '@rayselfs/cf-rule-engine/adapters/viewer-response'
|
|
68
|
+
*
|
|
69
|
+
* // Public API — static Access-Control-Allow-Origin: *
|
|
70
|
+
* export default defineViewerResponse([
|
|
71
|
+
* setCorsHeaders({ allowedOrigins: ORIGIN_WILDCARD }),
|
|
72
|
+
* ])
|
|
58
73
|
*
|
|
59
|
-
* //
|
|
60
|
-
* export default defineViewerResponse([
|
|
74
|
+
* // Restricted — echo only listed origins (supports wildcard subdomains)
|
|
75
|
+
* export default defineViewerResponse([
|
|
76
|
+
* setCorsHeaders({ allowedOrigins: ['https://*.viverse.com', 'https://sdk-api.viverse.com'] }),
|
|
77
|
+
* ])
|
|
61
78
|
*
|
|
62
|
-
* // Echo origin
|
|
79
|
+
* // Echo any origin (e.g. for credentialed requests)
|
|
63
80
|
* export default defineViewerResponse([
|
|
64
|
-
* setCorsHeaders({
|
|
65
|
-
* allowedOrigins: ['https://www.example.com', 'https://*.example.com'],
|
|
66
|
-
* allowOriginEcho: true,
|
|
67
|
-
* allowCredentials: true,
|
|
68
|
-
* allowedMethods: 'GET, POST, PUT, DELETE, OPTIONS',
|
|
69
|
-
* maxAge: 86400,
|
|
70
|
-
* }),
|
|
81
|
+
* setCorsHeaders({ allowedOrigins: ORIGIN_ECHO, allowCredentials: true }),
|
|
71
82
|
* ])
|
|
72
83
|
* ```
|
|
73
84
|
*/
|
|
74
|
-
declare function setCorsHeaders(options
|
|
85
|
+
declare function setCorsHeaders(options: CorsOptions): ResponseBehaviorFn;
|
|
75
86
|
|
|
76
|
-
export { type CorsOptions, setCorsHeaders };
|
|
87
|
+
export { type CorsOptions, type Methods, ORIGIN_ECHO, ORIGIN_WILDCARD, type Origin, type OriginEcho, type OriginPolicy, type OriginWildcard, setCorsHeaders };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
methodIs
|
|
3
3
|
} from "./chunk-PY3JMRDG.js";
|
|
4
|
+
import {
|
|
5
|
+
ORIGIN_ECHO,
|
|
6
|
+
ORIGIN_WILDCARD
|
|
7
|
+
} from "./chunk-PI7RKMGS.js";
|
|
4
8
|
|
|
5
9
|
// src/helpers/preflight-request.ts
|
|
6
10
|
function matchesOriginPattern(origin, pattern) {
|
|
@@ -10,27 +14,33 @@ function matchesOriginPattern(origin, pattern) {
|
|
|
10
14
|
return new RegExp(`^${escaped}$`).test(origin);
|
|
11
15
|
}
|
|
12
16
|
function preflightRequest(options) {
|
|
13
|
-
const allowedOrigins = options
|
|
14
|
-
const allowedMethods = options
|
|
15
|
-
const allowedHeaders = options
|
|
16
|
-
const allowCredentials = options
|
|
17
|
-
const maxAge = options
|
|
17
|
+
const { allowedOrigins } = options;
|
|
18
|
+
const allowedMethods = options.allowedMethods ?? ["GET", "POST", "OPTIONS"];
|
|
19
|
+
const allowedHeaders = options.allowedHeaders ?? ["Content-Type", "Cache-Control", "Pragma", "Range"];
|
|
20
|
+
const allowCredentials = options.allowCredentials ?? false;
|
|
21
|
+
const maxAge = options.maxAge;
|
|
18
22
|
return {
|
|
19
23
|
criteria: methodIs(["OPTIONS"]),
|
|
20
24
|
behavior: (request) => {
|
|
21
25
|
let allowOrigin;
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
if (allowedOrigins === ORIGIN_WILDCARD) {
|
|
27
|
+
allowOrigin = "*";
|
|
28
|
+
} else if (allowedOrigins === ORIGIN_ECHO) {
|
|
29
|
+
allowOrigin = request.headers["origin"]?.value;
|
|
25
30
|
} else {
|
|
26
|
-
|
|
31
|
+
const originHeader = request.headers["origin"]?.value;
|
|
32
|
+
if (originHeader && allowedOrigins.some((p) => matchesOriginPattern(originHeader, p))) {
|
|
33
|
+
allowOrigin = originHeader;
|
|
34
|
+
}
|
|
27
35
|
}
|
|
28
36
|
const headers = {
|
|
29
37
|
"cache-control": { value: "no-store" },
|
|
30
|
-
"access-control-allow-
|
|
31
|
-
"access-control-allow-
|
|
32
|
-
"access-control-allow-headers": { value: allowedHeaders }
|
|
38
|
+
"access-control-allow-methods": { value: allowedMethods.join(", ") },
|
|
39
|
+
"access-control-allow-headers": { value: allowedHeaders.join(", ") }
|
|
33
40
|
};
|
|
41
|
+
if (allowOrigin !== void 0) {
|
|
42
|
+
headers["access-control-allow-origin"] = { value: allowOrigin };
|
|
43
|
+
}
|
|
34
44
|
if (allowCredentials) {
|
|
35
45
|
headers["access-control-allow-credentials"] = { value: "true" };
|
|
36
46
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/behaviors/set-cors-headers.ts
|
|
2
|
+
var ORIGIN_WILDCARD = "*";
|
|
3
|
+
var ORIGIN_ECHO = "echo";
|
|
2
4
|
function matchesOriginPattern(origin, pattern) {
|
|
3
5
|
if (pattern === "*") return true;
|
|
4
6
|
if (!pattern.includes("*")) return origin === pattern;
|
|
@@ -6,26 +8,33 @@ function matchesOriginPattern(origin, pattern) {
|
|
|
6
8
|
return new RegExp(`^${escaped}$`).test(origin);
|
|
7
9
|
}
|
|
8
10
|
function setCorsHeaders(options) {
|
|
9
|
-
const allowedOrigins = options
|
|
10
|
-
const allowedMethods = options?.allowedMethods ?? "GET, POST, OPTIONS";
|
|
11
|
-
const allowedHeaders = options?.allowedHeaders ?? "Content-Type, Cache-Control, Pragma, Range";
|
|
11
|
+
const { allowedOrigins } = options;
|
|
12
12
|
return (request, response) => {
|
|
13
|
-
let allowOrigin
|
|
14
|
-
if (
|
|
13
|
+
let allowOrigin;
|
|
14
|
+
if (allowedOrigins === ORIGIN_WILDCARD) {
|
|
15
|
+
allowOrigin = "*";
|
|
16
|
+
} else if (allowedOrigins === ORIGIN_ECHO) {
|
|
17
|
+
allowOrigin = request.headers["origin"]?.value;
|
|
18
|
+
} else {
|
|
15
19
|
const originHeader = request.headers["origin"]?.value;
|
|
16
20
|
if (originHeader && allowedOrigins.some((p) => matchesOriginPattern(originHeader, p))) {
|
|
17
21
|
allowOrigin = originHeader;
|
|
18
22
|
}
|
|
19
23
|
}
|
|
24
|
+
if (allowOrigin === void 0) return response;
|
|
20
25
|
const corsHeaders = {
|
|
21
|
-
"access-control-allow-origin": { value: allowOrigin }
|
|
22
|
-
"access-control-allow-methods": { value: allowedMethods },
|
|
23
|
-
"access-control-allow-headers": { value: allowedHeaders }
|
|
26
|
+
"access-control-allow-origin": { value: allowOrigin }
|
|
24
27
|
};
|
|
25
|
-
if (options
|
|
28
|
+
if (options.allowedMethods !== void 0) {
|
|
29
|
+
corsHeaders["access-control-allow-methods"] = { value: options.allowedMethods.join(", ") };
|
|
30
|
+
}
|
|
31
|
+
if (options.allowedHeaders !== void 0) {
|
|
32
|
+
corsHeaders["access-control-allow-headers"] = { value: options.allowedHeaders.join(", ") };
|
|
33
|
+
}
|
|
34
|
+
if (options.allowCredentials) {
|
|
26
35
|
corsHeaders["access-control-allow-credentials"] = { value: "true" };
|
|
27
36
|
}
|
|
28
|
-
if (options
|
|
37
|
+
if (options.maxAge !== void 0) {
|
|
29
38
|
corsHeaders["access-control-max-age"] = { value: String(options.maxAge) };
|
|
30
39
|
}
|
|
31
40
|
return Object.assign({}, response, {
|
|
@@ -35,5 +44,7 @@ function setCorsHeaders(options) {
|
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
export {
|
|
47
|
+
ORIGIN_WILDCARD,
|
|
48
|
+
ORIGIN_ECHO,
|
|
38
49
|
setCorsHeaders
|
|
39
50
|
};
|