@kaito-http/core 4.0.0-beta.6 → 4.0.0-beta.7
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/dist/cors/cors.cjs +13 -6
- package/dist/cors/cors.d.cts +61 -20
- package/dist/cors/cors.d.ts +61 -20
- package/dist/cors/cors.js +13 -6
- package/package.json +1 -1
package/dist/cors/cors.cjs
CHANGED
|
@@ -28,13 +28,20 @@ function experimental_createOriginMatcher(origins) {
|
|
|
28
28
|
if (origins.length === 0) {
|
|
29
29
|
return () => false;
|
|
30
30
|
}
|
|
31
|
+
const escapedCharsRegex = /[.+?^${}()|[\]\\]/g;
|
|
31
32
|
const source = origins.map((origin) => {
|
|
32
|
-
if (origin.
|
|
33
|
-
const
|
|
34
|
-
|
|
33
|
+
if (origin.includes("://*.")) {
|
|
34
|
+
const parts = origin.split("://");
|
|
35
|
+
if (parts.length !== 2) {
|
|
36
|
+
throw new Error(`Invalid origin pattern: ${origin}. Must include protocol (e.g., https://*.example.com)`);
|
|
37
|
+
}
|
|
38
|
+
const [protocol, rest] = parts;
|
|
39
|
+
const domain = rest.slice(2).replace(escapedCharsRegex, "\\$&");
|
|
40
|
+
const pattern = `^${protocol.replace(escapedCharsRegex, "\\$&")}:\\/\\/[^.]+\\.${domain}$`;
|
|
41
|
+
return pattern;
|
|
35
42
|
} else {
|
|
36
|
-
const
|
|
37
|
-
return
|
|
43
|
+
const pattern = `^${origin.replace(escapedCharsRegex, "\\$&")}$`;
|
|
44
|
+
return pattern;
|
|
38
45
|
}
|
|
39
46
|
}).join("|");
|
|
40
47
|
const regex = new RegExp(source);
|
|
@@ -46,7 +53,7 @@ function experimental_createCORSTransform(origins) {
|
|
|
46
53
|
const origin = request.headers.get("Origin");
|
|
47
54
|
if (origin && matcher(origin)) {
|
|
48
55
|
response.headers.set("Access-Control-Allow-Origin", origin);
|
|
49
|
-
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
56
|
+
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
|
|
50
57
|
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
51
58
|
response.headers.set("Access-Control-Max-Age", "86400");
|
|
52
59
|
response.headers.set("Access-Control-Allow-Credentials", "true");
|
package/dist/cors/cors.d.cts
CHANGED
|
@@ -1,31 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Creates a function that matches origins against a predefined set of patterns, supporting wildcards.
|
|
3
|
-
* The matcher handles both exact matches and wildcard subdomain patterns
|
|
3
|
+
* The matcher handles both exact matches and wildcard subdomain patterns.
|
|
4
4
|
*
|
|
5
5
|
* **⚠️ This API is experimental and may change or even be removed in the future. ⚠️**
|
|
6
6
|
*
|
|
7
7
|
* @param origins Array of origin patterns to match against.
|
|
8
|
-
*
|
|
8
|
+
* Each pattern MUST include the protocol (http:// or https://).
|
|
9
|
+
* Two types of patterns are supported:
|
|
10
|
+
* 1. Exact matches (e.g., 'https://example.com') - matches only the exact domain with exact protocol
|
|
11
|
+
* 2. Wildcard subdomain patterns (e.g., 'https://*.example.com') - matches ONLY subdomains with exact protocol
|
|
12
|
+
*
|
|
13
|
+
* Important matching rules:
|
|
14
|
+
* - Protocol is always matched exactly - if you need both HTTP and HTTPS, include both patterns
|
|
15
|
+
* - Wildcard patterns (e.g., 'https://*.example.com') will ONLY match subdomains, NOT the root domain
|
|
16
|
+
* - To match both subdomains AND the root domain, include both patterns:
|
|
17
|
+
* ['https://*.example.com', 'https://example.com']
|
|
18
|
+
*
|
|
9
19
|
* @returns A function that tests if an origin matches any of the patterns
|
|
10
20
|
*
|
|
11
21
|
* @example
|
|
12
22
|
* ```typescript
|
|
13
23
|
* const allowedOrigins = [
|
|
14
|
-
*
|
|
15
|
-
* '
|
|
24
|
+
* // Exact matches - protocol required
|
|
25
|
+
* 'https://example.com', // matches only https://example.com
|
|
26
|
+
* 'http://example.com', // matches only http://example.com
|
|
27
|
+
*
|
|
28
|
+
* // Wildcard subdomain matches - protocol required
|
|
29
|
+
* 'https://*.example.com', // matches https://app.example.com, https://api.example.com
|
|
30
|
+
* // does NOT match https://example.com
|
|
31
|
+
*
|
|
32
|
+
* // To match both HTTP and HTTPS, include both
|
|
33
|
+
* 'https://*.staging.com', // matches https://app.staging.com
|
|
34
|
+
* 'http://*.staging.com', // matches http://app.staging.com
|
|
35
|
+
*
|
|
36
|
+
* // To match both subdomains and root domain, include both
|
|
37
|
+
* 'https://*.production.com', // matches https://app.production.com
|
|
38
|
+
* 'https://production.com', // matches https://production.com
|
|
16
39
|
* ];
|
|
17
40
|
*
|
|
18
41
|
* const matcher = createOriginMatcher(allowedOrigins);
|
|
19
42
|
*
|
|
20
|
-
* // Exact
|
|
21
|
-
*
|
|
22
|
-
*
|
|
43
|
+
* // Exact matches
|
|
44
|
+
* matcher('https://example.com'); // true
|
|
45
|
+
* matcher('http://example.com'); // true
|
|
23
46
|
*
|
|
24
|
-
* //
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
47
|
+
* // Subdomain matches (protocol specific)
|
|
48
|
+
* matcher('https://app.example.com'); // true
|
|
49
|
+
* matcher('http://app.example.com'); // false - wrong protocol
|
|
50
|
+
*
|
|
51
|
+
* // Root domain with wildcard pattern
|
|
52
|
+
* matcher('https://example.com'); // false - wildcards don't match root
|
|
53
|
+
* matcher('https://production.com'); // true - matched by exact pattern
|
|
29
54
|
* ```
|
|
30
55
|
*/
|
|
31
56
|
declare function experimental_createOriginMatcher(origins: string[]): (origin: string) => boolean;
|
|
@@ -38,15 +63,31 @@ declare function experimental_createOriginMatcher(origins: string[]): (origin: s
|
|
|
38
63
|
* @returns A function that will mutate the Response object by applying the CORS headers
|
|
39
64
|
* @example
|
|
40
65
|
* ```ts
|
|
41
|
-
* const cors =
|
|
42
|
-
*
|
|
43
|
-
*
|
|
66
|
+
* const cors = experimental_createCORSTransform([
|
|
67
|
+
* // Exact matches
|
|
68
|
+
* 'https://example.com',
|
|
69
|
+
* 'http://localhost:3000',
|
|
70
|
+
*
|
|
71
|
+
* // Wildcard subdomain matches
|
|
72
|
+
* 'https://*.myapp.com', // matches https://dashboard.myapp.com
|
|
73
|
+
* 'http://*.myapp.com', // matches http://dashboard.myapp.com
|
|
74
|
+
*
|
|
75
|
+
* // Match both subdomain and root domain
|
|
76
|
+
* 'https://*.staging.com', // matches https://app.staging.com
|
|
77
|
+
* 'https://staging.com' // matches https://staging.com
|
|
78
|
+
* ]);
|
|
44
79
|
*
|
|
45
|
-
* const
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
80
|
+
* const router = create({
|
|
81
|
+
* before: async req => {
|
|
82
|
+
* if (req.method === 'OPTIONS') {
|
|
83
|
+
* // Return early to skip the router. This response still gets passed to `.transform()`
|
|
84
|
+
* // So our CORS headers will still be applied
|
|
85
|
+
* return new Response(null, {status: 204});
|
|
86
|
+
* }
|
|
87
|
+
* },
|
|
88
|
+
* transform: async (request, response) => {
|
|
89
|
+
* cors(request, response);
|
|
90
|
+
* }
|
|
50
91
|
* });
|
|
51
92
|
* ```
|
|
52
93
|
*/
|
package/dist/cors/cors.d.ts
CHANGED
|
@@ -1,31 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Creates a function that matches origins against a predefined set of patterns, supporting wildcards.
|
|
3
|
-
* The matcher handles both exact matches and wildcard subdomain patterns
|
|
3
|
+
* The matcher handles both exact matches and wildcard subdomain patterns.
|
|
4
4
|
*
|
|
5
5
|
* **⚠️ This API is experimental and may change or even be removed in the future. ⚠️**
|
|
6
6
|
*
|
|
7
7
|
* @param origins Array of origin patterns to match against.
|
|
8
|
-
*
|
|
8
|
+
* Each pattern MUST include the protocol (http:// or https://).
|
|
9
|
+
* Two types of patterns are supported:
|
|
10
|
+
* 1. Exact matches (e.g., 'https://example.com') - matches only the exact domain with exact protocol
|
|
11
|
+
* 2. Wildcard subdomain patterns (e.g., 'https://*.example.com') - matches ONLY subdomains with exact protocol
|
|
12
|
+
*
|
|
13
|
+
* Important matching rules:
|
|
14
|
+
* - Protocol is always matched exactly - if you need both HTTP and HTTPS, include both patterns
|
|
15
|
+
* - Wildcard patterns (e.g., 'https://*.example.com') will ONLY match subdomains, NOT the root domain
|
|
16
|
+
* - To match both subdomains AND the root domain, include both patterns:
|
|
17
|
+
* ['https://*.example.com', 'https://example.com']
|
|
18
|
+
*
|
|
9
19
|
* @returns A function that tests if an origin matches any of the patterns
|
|
10
20
|
*
|
|
11
21
|
* @example
|
|
12
22
|
* ```typescript
|
|
13
23
|
* const allowedOrigins = [
|
|
14
|
-
*
|
|
15
|
-
* '
|
|
24
|
+
* // Exact matches - protocol required
|
|
25
|
+
* 'https://example.com', // matches only https://example.com
|
|
26
|
+
* 'http://example.com', // matches only http://example.com
|
|
27
|
+
*
|
|
28
|
+
* // Wildcard subdomain matches - protocol required
|
|
29
|
+
* 'https://*.example.com', // matches https://app.example.com, https://api.example.com
|
|
30
|
+
* // does NOT match https://example.com
|
|
31
|
+
*
|
|
32
|
+
* // To match both HTTP and HTTPS, include both
|
|
33
|
+
* 'https://*.staging.com', // matches https://app.staging.com
|
|
34
|
+
* 'http://*.staging.com', // matches http://app.staging.com
|
|
35
|
+
*
|
|
36
|
+
* // To match both subdomains and root domain, include both
|
|
37
|
+
* 'https://*.production.com', // matches https://app.production.com
|
|
38
|
+
* 'https://production.com', // matches https://production.com
|
|
16
39
|
* ];
|
|
17
40
|
*
|
|
18
41
|
* const matcher = createOriginMatcher(allowedOrigins);
|
|
19
42
|
*
|
|
20
|
-
* // Exact
|
|
21
|
-
*
|
|
22
|
-
*
|
|
43
|
+
* // Exact matches
|
|
44
|
+
* matcher('https://example.com'); // true
|
|
45
|
+
* matcher('http://example.com'); // true
|
|
23
46
|
*
|
|
24
|
-
* //
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
47
|
+
* // Subdomain matches (protocol specific)
|
|
48
|
+
* matcher('https://app.example.com'); // true
|
|
49
|
+
* matcher('http://app.example.com'); // false - wrong protocol
|
|
50
|
+
*
|
|
51
|
+
* // Root domain with wildcard pattern
|
|
52
|
+
* matcher('https://example.com'); // false - wildcards don't match root
|
|
53
|
+
* matcher('https://production.com'); // true - matched by exact pattern
|
|
29
54
|
* ```
|
|
30
55
|
*/
|
|
31
56
|
declare function experimental_createOriginMatcher(origins: string[]): (origin: string) => boolean;
|
|
@@ -38,15 +63,31 @@ declare function experimental_createOriginMatcher(origins: string[]): (origin: s
|
|
|
38
63
|
* @returns A function that will mutate the Response object by applying the CORS headers
|
|
39
64
|
* @example
|
|
40
65
|
* ```ts
|
|
41
|
-
* const cors =
|
|
42
|
-
*
|
|
43
|
-
*
|
|
66
|
+
* const cors = experimental_createCORSTransform([
|
|
67
|
+
* // Exact matches
|
|
68
|
+
* 'https://example.com',
|
|
69
|
+
* 'http://localhost:3000',
|
|
70
|
+
*
|
|
71
|
+
* // Wildcard subdomain matches
|
|
72
|
+
* 'https://*.myapp.com', // matches https://dashboard.myapp.com
|
|
73
|
+
* 'http://*.myapp.com', // matches http://dashboard.myapp.com
|
|
74
|
+
*
|
|
75
|
+
* // Match both subdomain and root domain
|
|
76
|
+
* 'https://*.staging.com', // matches https://app.staging.com
|
|
77
|
+
* 'https://staging.com' // matches https://staging.com
|
|
78
|
+
* ]);
|
|
44
79
|
*
|
|
45
|
-
* const
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
80
|
+
* const router = create({
|
|
81
|
+
* before: async req => {
|
|
82
|
+
* if (req.method === 'OPTIONS') {
|
|
83
|
+
* // Return early to skip the router. This response still gets passed to `.transform()`
|
|
84
|
+
* // So our CORS headers will still be applied
|
|
85
|
+
* return new Response(null, {status: 204});
|
|
86
|
+
* }
|
|
87
|
+
* },
|
|
88
|
+
* transform: async (request, response) => {
|
|
89
|
+
* cors(request, response);
|
|
90
|
+
* }
|
|
50
91
|
* });
|
|
51
92
|
* ```
|
|
52
93
|
*/
|
package/dist/cors/cors.js
CHANGED
|
@@ -3,13 +3,20 @@ function experimental_createOriginMatcher(origins) {
|
|
|
3
3
|
if (origins.length === 0) {
|
|
4
4
|
return () => false;
|
|
5
5
|
}
|
|
6
|
+
const escapedCharsRegex = /[.+?^${}()|[\]\\]/g;
|
|
6
7
|
const source = origins.map((origin) => {
|
|
7
|
-
if (origin.
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
if (origin.includes("://*.")) {
|
|
9
|
+
const parts = origin.split("://");
|
|
10
|
+
if (parts.length !== 2) {
|
|
11
|
+
throw new Error(`Invalid origin pattern: ${origin}. Must include protocol (e.g., https://*.example.com)`);
|
|
12
|
+
}
|
|
13
|
+
const [protocol, rest] = parts;
|
|
14
|
+
const domain = rest.slice(2).replace(escapedCharsRegex, "\\$&");
|
|
15
|
+
const pattern = `^${protocol.replace(escapedCharsRegex, "\\$&")}:\\/\\/[^.]+\\.${domain}$`;
|
|
16
|
+
return pattern;
|
|
10
17
|
} else {
|
|
11
|
-
const
|
|
12
|
-
return
|
|
18
|
+
const pattern = `^${origin.replace(escapedCharsRegex, "\\$&")}$`;
|
|
19
|
+
return pattern;
|
|
13
20
|
}
|
|
14
21
|
}).join("|");
|
|
15
22
|
const regex = new RegExp(source);
|
|
@@ -21,7 +28,7 @@ function experimental_createCORSTransform(origins) {
|
|
|
21
28
|
const origin = request.headers.get("Origin");
|
|
22
29
|
if (origin && matcher(origin)) {
|
|
23
30
|
response.headers.set("Access-Control-Allow-Origin", origin);
|
|
24
|
-
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
31
|
+
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
|
|
25
32
|
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
26
33
|
response.headers.set("Access-Control-Max-Age", "86400");
|
|
27
34
|
response.headers.set("Access-Control-Allow-Credentials", "true");
|