@interopio/gateway-server 0.8.1-beta.2 → 0.9.0-beta.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/changelog.md +13 -0
- package/dist/index.cjs +57 -201
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +57 -201
- package/dist/index.js.map +4 -4
- package/dist/web/test.js +12 -11
- package/dist/web/test.js.map +2 -2
- package/gateway-server.d.ts +1 -1
- package/package.json +2 -2
package/changelog.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
# Change Log
|
|
4
4
|
|
|
5
|
+
## 0.9.0-beta.1 (2025-09-03)
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- upgrade @interopio/gateway to 0.12.2-beta.0
|
|
9
|
+
|
|
10
|
+
## 0.9.0-beta.0 (2025-09-02)
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- allow disabling cors protocol handling via config
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- cors config source autoconfiguration (match only by path to properly handle preflight requests)
|
|
17
|
+
|
|
5
18
|
## 0.8.1-beta.2 (2025-08-27)
|
|
6
19
|
|
|
7
20
|
### Changed
|
package/dist/index.cjs
CHANGED
|
@@ -44,7 +44,7 @@ var import_node_http2 = __toESM(require("node:http"), 1);
|
|
|
44
44
|
var import_node_https = __toESM(require("node:https"), 1);
|
|
45
45
|
var import_node_fs = require("node:fs");
|
|
46
46
|
var import_node_async_hooks4 = require("node:async_hooks");
|
|
47
|
-
var
|
|
47
|
+
var import_gateway7 = require("@interopio/gateway");
|
|
48
48
|
|
|
49
49
|
// src/logger.ts
|
|
50
50
|
var import_gateway = require("@interopio/gateway");
|
|
@@ -1402,14 +1402,15 @@ upgradeMatcher.toString = () => "websocket upgrade";
|
|
|
1402
1402
|
// src/app/route.ts
|
|
1403
1403
|
var import_gateway4 = require("@interopio/gateway");
|
|
1404
1404
|
async function configure(app, config, routes) {
|
|
1405
|
-
const applyCors = (
|
|
1405
|
+
const applyCors = (request, options) => {
|
|
1406
1406
|
if (options?.cors) {
|
|
1407
1407
|
const cors = options.cors === true ? {
|
|
1408
1408
|
allowOrigins: options.origins?.allow?.map(import_gateway4.IOGateway.Filtering.regexify),
|
|
1409
|
-
allowMethods:
|
|
1410
|
-
allowCredentials: options.authorize?.access !== "permitted"
|
|
1409
|
+
allowMethods: request.method === void 0 ? ["*"] : [request.method],
|
|
1410
|
+
allowCredentials: options.authorize?.access !== "permitted" ? true : void 0
|
|
1411
1411
|
} : options.cors;
|
|
1412
|
-
|
|
1412
|
+
const path = request.path;
|
|
1413
|
+
routes.cors.push([path, cors]);
|
|
1413
1414
|
}
|
|
1414
1415
|
};
|
|
1415
1416
|
const configurer = new class {
|
|
@@ -1419,7 +1420,7 @@ async function configure(app, config, routes) {
|
|
|
1419
1420
|
if (options?.authorize) {
|
|
1420
1421
|
routes.authorize.push([matcher, options.authorize]);
|
|
1421
1422
|
}
|
|
1422
|
-
applyCors(
|
|
1423
|
+
applyCors(request, options);
|
|
1423
1424
|
const middleware = async (exchange, next) => {
|
|
1424
1425
|
const { match: match2, variables } = await matcher(exchange);
|
|
1425
1426
|
if (match2) {
|
|
@@ -1752,210 +1753,62 @@ var matchingCorsConfigSource = (opts) => {
|
|
|
1752
1753
|
};
|
|
1753
1754
|
};
|
|
1754
1755
|
|
|
1755
|
-
// src/mock/server/exchange.ts
|
|
1756
|
-
var import_web = __toESM(require("node:stream/web"), 1);
|
|
1757
|
-
var MockServerHttpRequest = class extends AbstractHttpRequest {
|
|
1758
|
-
#url;
|
|
1759
|
-
#body;
|
|
1760
|
-
upgrade = false;
|
|
1761
|
-
constructor(url, method) {
|
|
1762
|
-
super(new MapHttpHeaders());
|
|
1763
|
-
if (typeof url === "string") {
|
|
1764
|
-
if (URL.canParse(url)) {
|
|
1765
|
-
url = new URL(url);
|
|
1766
|
-
} else if (URL.canParse(url, "http://localhost")) {
|
|
1767
|
-
url = new URL(url, "http://localhost");
|
|
1768
|
-
} else {
|
|
1769
|
-
throw new TypeError("URL cannot parse url");
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
this.#url = url;
|
|
1773
|
-
this.method = method ?? "GET";
|
|
1774
|
-
this.setHeader("Host", this.#url.hostname);
|
|
1775
|
-
this.path = this.#url.pathname ?? "/";
|
|
1776
|
-
}
|
|
1777
|
-
method;
|
|
1778
|
-
path;
|
|
1779
|
-
get host() {
|
|
1780
|
-
return super.parseHost(this.#url.host);
|
|
1781
|
-
}
|
|
1782
|
-
get protocol() {
|
|
1783
|
-
return super.parseProtocol(this.#url.protocol.slice(0, -1));
|
|
1784
|
-
}
|
|
1785
|
-
get body() {
|
|
1786
|
-
if (this.#body !== void 0) {
|
|
1787
|
-
const blob = this.#body;
|
|
1788
|
-
const asyncIterator = async function* () {
|
|
1789
|
-
const bytes = await blob.bytes();
|
|
1790
|
-
yield bytes;
|
|
1791
|
-
}();
|
|
1792
|
-
return import_web.default.ReadableStream.from(asyncIterator);
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
|
-
blob() {
|
|
1796
|
-
const body = this.#body;
|
|
1797
|
-
return body ? Promise.resolve(body) : Promise.reject(new Error(`no body set`));
|
|
1798
|
-
}
|
|
1799
|
-
async text() {
|
|
1800
|
-
const blob = await this.blob();
|
|
1801
|
-
return await blob.text();
|
|
1802
|
-
}
|
|
1803
|
-
async formData() {
|
|
1804
|
-
const blob = await this.blob();
|
|
1805
|
-
const text = await blob.text();
|
|
1806
|
-
return new URLSearchParams(text);
|
|
1807
|
-
}
|
|
1808
|
-
async json() {
|
|
1809
|
-
const blob = await this.blob();
|
|
1810
|
-
if (blob.size === 0) {
|
|
1811
|
-
return void 0;
|
|
1812
|
-
}
|
|
1813
|
-
const text = await blob.text();
|
|
1814
|
-
return JSON.parse(text);
|
|
1815
|
-
}
|
|
1816
|
-
async writeBody(body) {
|
|
1817
|
-
if (body === void 0) {
|
|
1818
|
-
this.#body = new Blob([]);
|
|
1819
|
-
return;
|
|
1820
|
-
}
|
|
1821
|
-
if (body instanceof ReadableStream) {
|
|
1822
|
-
const chunks = [];
|
|
1823
|
-
const reader = body.getReader();
|
|
1824
|
-
let done = false;
|
|
1825
|
-
while (!done) {
|
|
1826
|
-
const { value, done: readDone } = await reader.read();
|
|
1827
|
-
if (readDone) {
|
|
1828
|
-
done = true;
|
|
1829
|
-
} else {
|
|
1830
|
-
chunks.push(value);
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
this.#body = new Blob(chunks);
|
|
1834
|
-
} else {
|
|
1835
|
-
body = await body;
|
|
1836
|
-
if (typeof body === "string") {
|
|
1837
|
-
this.#body = new Blob([body], { type: "text/plain" });
|
|
1838
|
-
} else {
|
|
1839
|
-
this.#body = new Blob([body]);
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
if (!this.headers.has("content-type")) {
|
|
1843
|
-
this.setHeader("Content-Type", this.#body.type || "application/octet-stream");
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
get URL() {
|
|
1847
|
-
return new URL(this.path + this.#url.search + this.#url.hash, `${this.protocol}://${this.host}`);
|
|
1848
|
-
}
|
|
1849
|
-
addHeader(name, value) {
|
|
1850
|
-
this.headers.add(name, value);
|
|
1851
|
-
return this;
|
|
1852
|
-
}
|
|
1853
|
-
setHeader(name, value) {
|
|
1854
|
-
this.headers.set(name, value);
|
|
1855
|
-
return this;
|
|
1856
|
-
}
|
|
1857
|
-
};
|
|
1858
|
-
var MockServerHttpResponse = class extends AbstractServerHttpResponse {
|
|
1859
|
-
#writeHandler;
|
|
1860
|
-
#body = () => {
|
|
1861
|
-
throw new Error("No content was written to the response body nor end was called on this response.");
|
|
1862
|
-
};
|
|
1863
|
-
constructor() {
|
|
1864
|
-
super(new MapHttpHeaders());
|
|
1865
|
-
this.#writeHandler = async (body) => {
|
|
1866
|
-
const chunks = [];
|
|
1867
|
-
let bodyStream;
|
|
1868
|
-
this.#body = () => {
|
|
1869
|
-
bodyStream ??= import_web.default.ReadableStream.from(chunks);
|
|
1870
|
-
return bodyStream;
|
|
1871
|
-
};
|
|
1872
|
-
const reader = body.getReader();
|
|
1873
|
-
let done = false;
|
|
1874
|
-
do {
|
|
1875
|
-
const { value, done: readDone } = await reader.read();
|
|
1876
|
-
if (readDone) {
|
|
1877
|
-
done = true;
|
|
1878
|
-
} else {
|
|
1879
|
-
chunks.push(value);
|
|
1880
|
-
}
|
|
1881
|
-
} while (!done);
|
|
1882
|
-
return true;
|
|
1883
|
-
};
|
|
1884
|
-
}
|
|
1885
|
-
get statusCode() {
|
|
1886
|
-
return super.statusCode;
|
|
1887
|
-
}
|
|
1888
|
-
set writeHandler(handler) {
|
|
1889
|
-
this.#body = () => {
|
|
1890
|
-
throw new Error("Not available with custom write handler");
|
|
1891
|
-
};
|
|
1892
|
-
this.#writeHandler = handler;
|
|
1893
|
-
}
|
|
1894
|
-
getNativeResponse() {
|
|
1895
|
-
throw new Error("This is a mock. No running server, no native response.");
|
|
1896
|
-
}
|
|
1897
|
-
applyStatusCode() {
|
|
1898
|
-
}
|
|
1899
|
-
applyHeaders() {
|
|
1900
|
-
}
|
|
1901
|
-
applyCookies() {
|
|
1902
|
-
for (const cookie of this.cookies) {
|
|
1903
|
-
this.headers.add("Set-Cookie", super.setCookieValue(cookie));
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
bodyInternal(body) {
|
|
1907
|
-
const it = async function* () {
|
|
1908
|
-
const resolved = await body;
|
|
1909
|
-
if (resolved === void 0) {
|
|
1910
|
-
return;
|
|
1911
|
-
}
|
|
1912
|
-
yield resolved;
|
|
1913
|
-
}();
|
|
1914
|
-
return this.#writeHandler(import_web.default.ReadableStream.from(it));
|
|
1915
|
-
}
|
|
1916
|
-
async end() {
|
|
1917
|
-
return this.doCommit(async () => {
|
|
1918
|
-
return await new Promise((resolve, reject) => {
|
|
1919
|
-
this.#writeHandler(import_web.default.ReadableStream.from([]));
|
|
1920
|
-
});
|
|
1921
|
-
});
|
|
1922
|
-
}
|
|
1923
|
-
getBody() {
|
|
1924
|
-
return this.#body();
|
|
1925
|
-
}
|
|
1926
|
-
};
|
|
1927
|
-
|
|
1928
1756
|
// src/app/cors.ts
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
request.setHeader("Upgrade", "websocket");
|
|
1932
|
-
request.upgrade = true;
|
|
1933
|
-
return new DefaultWebExchange(request, new MockServerHttpResponse());
|
|
1934
|
-
}
|
|
1935
|
-
async function createCorsConfigSource(context) {
|
|
1757
|
+
var import_gateway6 = require("@interopio/gateway");
|
|
1758
|
+
function createCorsConfigSource(context) {
|
|
1936
1759
|
const { sockets: routes, cors } = context;
|
|
1937
|
-
const defaultCorsConfig = combineCorsConfig(PERMIT_DEFAULT_CONFIG, context.corsConfig);
|
|
1760
|
+
const defaultCorsConfig = context.corsConfig === false ? void 0 : combineCorsConfig(PERMIT_DEFAULT_CONFIG, context.corsConfig);
|
|
1938
1761
|
const validatedConfigs = [];
|
|
1939
1762
|
for (const [path, route] of routes) {
|
|
1940
1763
|
let routeCorsConfig = defaultCorsConfig;
|
|
1941
|
-
const
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1764
|
+
for (const [matcher, config2] of cors) {
|
|
1765
|
+
if (import_gateway6.IOGateway.Filtering.valueMatches(matcher, path)) {
|
|
1766
|
+
if (config2 === void 0) {
|
|
1767
|
+
routeCorsConfig = void 0;
|
|
1768
|
+
} else {
|
|
1769
|
+
routeCorsConfig = routeCorsConfig === void 0 ? config2 : combineCorsConfig(routeCorsConfig, config2);
|
|
1770
|
+
}
|
|
1945
1771
|
}
|
|
1946
1772
|
}
|
|
1947
|
-
|
|
1773
|
+
const config = context.corsConfig === false ? void 0 : {
|
|
1948
1774
|
allowOrigins: route.originFilters?.allow,
|
|
1949
|
-
allowMethods: ["GET", "CONNECT"],
|
|
1950
|
-
allowHeaders: [
|
|
1775
|
+
allowMethods: ["GET", "CONNECT", "OPTIONS"],
|
|
1776
|
+
allowHeaders: [
|
|
1777
|
+
"Upgrade",
|
|
1778
|
+
"Connection",
|
|
1779
|
+
"Origin",
|
|
1780
|
+
"Sec-Websocket-Key",
|
|
1781
|
+
"Sec-Websocket-Version",
|
|
1782
|
+
"Sec-Websocket-Protocol",
|
|
1783
|
+
"Sec-Websocket-Extensions"
|
|
1784
|
+
],
|
|
1951
1785
|
exposeHeaders: ["Sec-Websocket-Accept", "Sec-Websocket-Protocol", "Sec-Websocket-Extensions"],
|
|
1952
|
-
allowCredentials: route.authorize?.access !== "permitted"
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1786
|
+
allowCredentials: route.authorize?.access !== "permitted" ? true : void 0
|
|
1787
|
+
};
|
|
1788
|
+
routeCorsConfig = routeCorsConfig === void 0 ? config : combineCorsConfig(routeCorsConfig, config);
|
|
1789
|
+
validatedConfigs.push([
|
|
1790
|
+
and([upgradeMatcher, pattern(path)]),
|
|
1791
|
+
validateCorsConfig(routeCorsConfig)
|
|
1792
|
+
]);
|
|
1955
1793
|
}
|
|
1794
|
+
const appConfigs = [];
|
|
1956
1795
|
for (const [matcher, config] of cors) {
|
|
1957
|
-
|
|
1958
|
-
|
|
1796
|
+
let [, routeCorsConfig] = appConfigs.find(([m]) => String(m) === String(matcher)) ?? [matcher, defaultCorsConfig];
|
|
1797
|
+
routeCorsConfig = routeCorsConfig === void 0 ? config : combineCorsConfig(routeCorsConfig, config);
|
|
1798
|
+
let added = false;
|
|
1799
|
+
for (const entry of appConfigs) {
|
|
1800
|
+
if (String(entry[0]) === String(matcher)) {
|
|
1801
|
+
entry[1] = routeCorsConfig;
|
|
1802
|
+
added = true;
|
|
1803
|
+
break;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
if (!added) {
|
|
1807
|
+
appConfigs.push([matcher, routeCorsConfig]);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
for (const [matcher, config] of appConfigs) {
|
|
1811
|
+
validatedConfigs.push([pattern(matcher), validateCorsConfig(config)]);
|
|
1959
1812
|
}
|
|
1960
1813
|
validatedConfigs.push([pattern(/\/api\/.*/), validateCorsConfig(defaultCorsConfig)]);
|
|
1961
1814
|
return matchingCorsConfigSource({ mappings: validatedConfigs });
|
|
@@ -2926,6 +2779,9 @@ function createSecurityConfig(context) {
|
|
|
2926
2779
|
authorize.push(["any-exchange", defaultAccess]);
|
|
2927
2780
|
return {
|
|
2928
2781
|
authorize,
|
|
2782
|
+
cors: {
|
|
2783
|
+
disabled: context.corsConfig === false
|
|
2784
|
+
},
|
|
2929
2785
|
basic: {
|
|
2930
2786
|
disabled: context.authConfig?.type !== "basic",
|
|
2931
2787
|
...context.authConfig?.basic
|
|
@@ -2937,7 +2793,7 @@ function createSecurityConfig(context) {
|
|
|
2937
2793
|
};
|
|
2938
2794
|
}
|
|
2939
2795
|
async function httpSecurity(context) {
|
|
2940
|
-
const corsConfigSource =
|
|
2796
|
+
const corsConfigSource = createCorsConfigSource(context);
|
|
2941
2797
|
const config = createSecurityConfig(context);
|
|
2942
2798
|
const { storage } = context;
|
|
2943
2799
|
return config_default(config, { storage, corsConfigSource });
|
|
@@ -3354,7 +3210,7 @@ var Factory = async (options) => {
|
|
|
3354
3210
|
storage: new import_node_async_hooks4.AsyncLocalStorage(),
|
|
3355
3211
|
sockets: /* @__PURE__ */ new Map()
|
|
3356
3212
|
};
|
|
3357
|
-
const gw =
|
|
3213
|
+
const gw = import_gateway7.IOGateway.Factory({ ...options.gateway });
|
|
3358
3214
|
if (options.gateway) {
|
|
3359
3215
|
const config = options.gateway;
|
|
3360
3216
|
await configure(async (configurer) => {
|