@jsenv/server 17.5.0 → 17.6.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/dist/jsenv_server.js
CHANGED
|
@@ -8485,12 +8485,16 @@ const serverPluginCORS = ({
|
|
|
8485
8485
|
return [];
|
|
8486
8486
|
}
|
|
8487
8487
|
|
|
8488
|
+
const allowedOriginChecker = createAllowedOriginChecker(
|
|
8489
|
+
accessControlAllowedOrigins,
|
|
8490
|
+
);
|
|
8491
|
+
|
|
8488
8492
|
return {
|
|
8489
8493
|
name: "jsenv:cors",
|
|
8490
8494
|
injectResponseProperties: (request) => {
|
|
8491
8495
|
const accessControlHeaders = generateAccessControlHeaders({
|
|
8492
8496
|
request,
|
|
8493
|
-
|
|
8497
|
+
allowedOriginChecker,
|
|
8494
8498
|
accessControlAllowRequestOrigin,
|
|
8495
8499
|
accessControlAllowedMethods,
|
|
8496
8500
|
accessControlAllowRequestMethod,
|
|
@@ -8507,11 +8511,53 @@ const serverPluginCORS = ({
|
|
|
8507
8511
|
};
|
|
8508
8512
|
};
|
|
8509
8513
|
|
|
8514
|
+
/**
|
|
8515
|
+
* An origin ("scheme://host:port") can never contain "*", so it is free to be
|
|
8516
|
+
* used as a wildcard standing for any run of characters except "/":
|
|
8517
|
+
* "https://pr-*-my-app.fly.dev" matches "https://pr-12-my-app.fly.dev".
|
|
8518
|
+
*/
|
|
8519
|
+
const createAllowedOriginChecker = (allowedOrigins) => {
|
|
8520
|
+
const literalOrigins = [];
|
|
8521
|
+
const originRegExps = [];
|
|
8522
|
+
for (const allowedOrigin of allowedOrigins) {
|
|
8523
|
+
if (allowedOrigin.includes("*")) {
|
|
8524
|
+
originRegExps.push(originPatternToRegExp(allowedOrigin));
|
|
8525
|
+
} else {
|
|
8526
|
+
literalOrigins.push(allowedOrigin);
|
|
8527
|
+
}
|
|
8528
|
+
}
|
|
8529
|
+
|
|
8530
|
+
return {
|
|
8531
|
+
// when the request origin cannot be reflected back we must still send a
|
|
8532
|
+
// single valid origin, never a pattern
|
|
8533
|
+
defaultOrigin: literalOrigins[0] ?? "*",
|
|
8534
|
+
isAllowed: (origin) => {
|
|
8535
|
+
if (literalOrigins.includes(origin)) {
|
|
8536
|
+
return true;
|
|
8537
|
+
}
|
|
8538
|
+
for (const originRegExp of originRegExps) {
|
|
8539
|
+
if (originRegExp.test(origin)) {
|
|
8540
|
+
return true;
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
return false;
|
|
8544
|
+
},
|
|
8545
|
+
};
|
|
8546
|
+
};
|
|
8547
|
+
|
|
8548
|
+
const originPatternToRegExp = (originPattern) => {
|
|
8549
|
+
const source = originPattern
|
|
8550
|
+
.split("*")
|
|
8551
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
8552
|
+
.join("[^/]*");
|
|
8553
|
+
return new RegExp(`^${source}$`);
|
|
8554
|
+
};
|
|
8555
|
+
|
|
8510
8556
|
// https://www.w3.org/TR/cors/
|
|
8511
8557
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
|
8512
8558
|
const generateAccessControlHeaders = ({
|
|
8513
8559
|
request: { headers },
|
|
8514
|
-
|
|
8560
|
+
allowedOriginChecker,
|
|
8515
8561
|
accessControlAllowRequestOrigin,
|
|
8516
8562
|
accessControlAllowedMethods,
|
|
8517
8563
|
accessControlAllowRequestMethod,
|
|
@@ -8538,7 +8584,7 @@ const generateAccessControlHeaders = ({
|
|
|
8538
8584
|
: null;
|
|
8539
8585
|
|
|
8540
8586
|
if (requestOrigin) {
|
|
8541
|
-
if (
|
|
8587
|
+
if (allowedOriginChecker.isAllowed(requestOrigin)) {
|
|
8542
8588
|
allowOrigin = requestOrigin;
|
|
8543
8589
|
vary.push("origin");
|
|
8544
8590
|
} else if (accessControlAllowRequestOrigin) {
|
|
@@ -8550,7 +8596,7 @@ const generateAccessControlHeaders = ({
|
|
|
8550
8596
|
}
|
|
8551
8597
|
|
|
8552
8598
|
if (allowOrigin === null) {
|
|
8553
|
-
allowOrigin =
|
|
8599
|
+
allowOrigin = allowedOriginChecker.defaultOrigin;
|
|
8554
8600
|
}
|
|
8555
8601
|
|
|
8556
8602
|
const allowedMethodArray = [...accessControlAllowedMethods];
|
package/package.json
CHANGED
|
@@ -35,12 +35,16 @@ export const serverPluginCORS = ({
|
|
|
35
35
|
return [];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
const allowedOriginChecker = createAllowedOriginChecker(
|
|
39
|
+
accessControlAllowedOrigins,
|
|
40
|
+
);
|
|
41
|
+
|
|
38
42
|
return {
|
|
39
43
|
name: "jsenv:cors",
|
|
40
44
|
injectResponseProperties: (request) => {
|
|
41
45
|
const accessControlHeaders = generateAccessControlHeaders({
|
|
42
46
|
request,
|
|
43
|
-
|
|
47
|
+
allowedOriginChecker,
|
|
44
48
|
accessControlAllowRequestOrigin,
|
|
45
49
|
accessControlAllowedMethods,
|
|
46
50
|
accessControlAllowRequestMethod,
|
|
@@ -57,11 +61,53 @@ export const serverPluginCORS = ({
|
|
|
57
61
|
};
|
|
58
62
|
};
|
|
59
63
|
|
|
64
|
+
/**
|
|
65
|
+
* An origin ("scheme://host:port") can never contain "*", so it is free to be
|
|
66
|
+
* used as a wildcard standing for any run of characters except "/":
|
|
67
|
+
* "https://pr-*-my-app.fly.dev" matches "https://pr-12-my-app.fly.dev".
|
|
68
|
+
*/
|
|
69
|
+
const createAllowedOriginChecker = (allowedOrigins) => {
|
|
70
|
+
const literalOrigins = [];
|
|
71
|
+
const originRegExps = [];
|
|
72
|
+
for (const allowedOrigin of allowedOrigins) {
|
|
73
|
+
if (allowedOrigin.includes("*")) {
|
|
74
|
+
originRegExps.push(originPatternToRegExp(allowedOrigin));
|
|
75
|
+
} else {
|
|
76
|
+
literalOrigins.push(allowedOrigin);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
// when the request origin cannot be reflected back we must still send a
|
|
82
|
+
// single valid origin, never a pattern
|
|
83
|
+
defaultOrigin: literalOrigins[0] ?? "*",
|
|
84
|
+
isAllowed: (origin) => {
|
|
85
|
+
if (literalOrigins.includes(origin)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
for (const originRegExp of originRegExps) {
|
|
89
|
+
if (originRegExp.test(origin)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const originPatternToRegExp = (originPattern) => {
|
|
99
|
+
const source = originPattern
|
|
100
|
+
.split("*")
|
|
101
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
102
|
+
.join("[^/]*");
|
|
103
|
+
return new RegExp(`^${source}$`);
|
|
104
|
+
};
|
|
105
|
+
|
|
60
106
|
// https://www.w3.org/TR/cors/
|
|
61
107
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
|
62
108
|
const generateAccessControlHeaders = ({
|
|
63
109
|
request: { headers },
|
|
64
|
-
|
|
110
|
+
allowedOriginChecker,
|
|
65
111
|
accessControlAllowRequestOrigin,
|
|
66
112
|
accessControlAllowedMethods,
|
|
67
113
|
accessControlAllowRequestMethod,
|
|
@@ -88,7 +134,7 @@ const generateAccessControlHeaders = ({
|
|
|
88
134
|
: null;
|
|
89
135
|
|
|
90
136
|
if (requestOrigin) {
|
|
91
|
-
if (
|
|
137
|
+
if (allowedOriginChecker.isAllowed(requestOrigin)) {
|
|
92
138
|
allowOrigin = requestOrigin;
|
|
93
139
|
vary.push("origin");
|
|
94
140
|
} else if (accessControlAllowRequestOrigin) {
|
|
@@ -100,7 +146,7 @@ const generateAccessControlHeaders = ({
|
|
|
100
146
|
}
|
|
101
147
|
|
|
102
148
|
if (allowOrigin === null) {
|
|
103
|
-
allowOrigin =
|
|
149
|
+
allowOrigin = allowedOriginChecker.defaultOrigin;
|
|
104
150
|
}
|
|
105
151
|
|
|
106
152
|
const allowedMethodArray = [...accessControlAllowedMethods];
|