@matter/nodejs 0.16.0-alpha.0-20251006-3fe1e7c57 → 0.16.0-alpha.0-20251013-89bb7099d
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/cjs/config.d.ts +1 -1
- package/dist/cjs/config.js +1 -1
- package/dist/cjs/environment/NodeJsEnvironment.d.ts +2 -0
- package/dist/cjs/environment/NodeJsEnvironment.d.ts.map +1 -1
- package/dist/cjs/environment/NodeJsEnvironment.js +15 -3
- package/dist/cjs/environment/NodeJsEnvironment.js.map +1 -1
- package/dist/cjs/environment/ProcessManager.d.ts +1 -0
- package/dist/cjs/environment/ProcessManager.d.ts.map +1 -1
- package/dist/cjs/environment/ProcessManager.js +8 -0
- package/dist/cjs/environment/ProcessManager.js.map +1 -1
- package/dist/cjs/net/NodeJsHttpEndpoint.d.ts +42 -0
- package/dist/cjs/net/NodeJsHttpEndpoint.d.ts.map +1 -0
- package/dist/cjs/net/NodeJsHttpEndpoint.js +304 -0
- package/dist/cjs/net/NodeJsHttpEndpoint.js.map +6 -0
- package/dist/cjs/net/NodeJsUdpChannel.d.ts +1 -1
- package/dist/cjs/net/NodeJsUdpChannel.d.ts.map +1 -1
- package/dist/cjs/net/NodeJsUdpChannel.js +31 -3
- package/dist/cjs/net/NodeJsUdpChannel.js.map +1 -1
- package/dist/cjs/net/WsAdapter.d.ts +25 -0
- package/dist/cjs/net/WsAdapter.d.ts.map +1 -0
- package/dist/cjs/net/WsAdapter.js +33 -0
- package/dist/cjs/net/WsAdapter.js.map +6 -0
- package/dist/cjs/net/index.d.ts +2 -0
- package/dist/cjs/net/index.d.ts.map +1 -1
- package/dist/cjs/net/index.js +2 -0
- package/dist/cjs/net/index.js.map +1 -1
- package/dist/esm/config.d.ts +1 -1
- package/dist/esm/config.js +1 -1
- package/dist/esm/environment/NodeJsEnvironment.d.ts +2 -0
- package/dist/esm/environment/NodeJsEnvironment.d.ts.map +1 -1
- package/dist/esm/environment/NodeJsEnvironment.js +16 -3
- package/dist/esm/environment/NodeJsEnvironment.js.map +1 -1
- package/dist/esm/environment/ProcessManager.d.ts +1 -0
- package/dist/esm/environment/ProcessManager.d.ts.map +1 -1
- package/dist/esm/environment/ProcessManager.js +8 -0
- package/dist/esm/environment/ProcessManager.js.map +1 -1
- package/dist/esm/net/NodeJsHttpEndpoint.d.ts +42 -0
- package/dist/esm/net/NodeJsHttpEndpoint.d.ts.map +1 -0
- package/dist/esm/net/NodeJsHttpEndpoint.js +284 -0
- package/dist/esm/net/NodeJsHttpEndpoint.js.map +6 -0
- package/dist/esm/net/NodeJsUdpChannel.d.ts +1 -1
- package/dist/esm/net/NodeJsUdpChannel.d.ts.map +1 -1
- package/dist/esm/net/NodeJsUdpChannel.js +34 -3
- package/dist/esm/net/NodeJsUdpChannel.js.map +1 -1
- package/dist/esm/net/WsAdapter.d.ts +25 -0
- package/dist/esm/net/WsAdapter.d.ts.map +1 -0
- package/dist/esm/net/WsAdapter.js +13 -0
- package/dist/esm/net/WsAdapter.js.map +6 -0
- package/dist/esm/net/index.d.ts +2 -0
- package/dist/esm/net/index.d.ts.map +1 -1
- package/dist/esm/net/index.js +2 -0
- package/dist/esm/net/index.js.map +1 -1
- package/package.json +10 -10
- package/src/config.ts +1 -1
- package/src/environment/NodeJsEnvironment.ts +21 -3
- package/src/environment/ProcessManager.ts +12 -0
- package/src/net/NodeJsHttpEndpoint.ts +358 -0
- package/src/net/NodeJsUdpChannel.ts +42 -3
- package/src/net/WsAdapter.ts +30 -0
- package/src/net/index.ts +2 -0
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import {
|
|
7
|
+
AddressInUseError,
|
|
8
|
+
BindError,
|
|
7
9
|
Bytes,
|
|
8
10
|
ChannelType,
|
|
9
11
|
createPromise,
|
|
10
12
|
Diagnostic,
|
|
13
|
+
ImplementationError,
|
|
11
14
|
isIPv4,
|
|
12
15
|
isIPv6,
|
|
13
16
|
Logger,
|
|
@@ -31,7 +34,20 @@ function createDgramSocket(host, port, options) {
|
|
|
31
34
|
try {
|
|
32
35
|
socket.close();
|
|
33
36
|
} catch (error2) {
|
|
34
|
-
logger.debug("Error closing socket", error2);
|
|
37
|
+
logger.debug("Error closing socket:", error2);
|
|
38
|
+
}
|
|
39
|
+
const code = error?.code;
|
|
40
|
+
let desc = `${host ? host : options.type === "udp4" ? "0.0.0.0" : "{::}"}`;
|
|
41
|
+
if (port !== void 0) {
|
|
42
|
+
desc = `${desc}:${port}`;
|
|
43
|
+
}
|
|
44
|
+
switch (code) {
|
|
45
|
+
case "EADDRINUSE":
|
|
46
|
+
error = new AddressInUseError(`Cannot bind ${desc} because port is already in use`);
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
error = new BindError(`Cannot bind to ${desc} (code ${code})`);
|
|
50
|
+
break;
|
|
35
51
|
}
|
|
36
52
|
reject(error);
|
|
37
53
|
};
|
|
@@ -55,11 +71,26 @@ class NodeJsUdpChannel {
|
|
|
55
71
|
#type;
|
|
56
72
|
#socket;
|
|
57
73
|
#netInterface;
|
|
58
|
-
static async create({ listeningPort, type, listeningAddress, netInterface }) {
|
|
59
|
-
|
|
74
|
+
static async create({ listeningPort, type, listeningAddress, netInterface, reuseAddress }) {
|
|
75
|
+
let dgramType;
|
|
76
|
+
switch (type) {
|
|
77
|
+
case "udp":
|
|
78
|
+
case "udp6":
|
|
79
|
+
dgramType = "udp6";
|
|
80
|
+
break;
|
|
81
|
+
case "udp4":
|
|
82
|
+
dgramType = "udp4";
|
|
83
|
+
break;
|
|
84
|
+
default:
|
|
85
|
+
throw new ImplementationError(`Unrecognized UDP socket type ${type}`);
|
|
86
|
+
}
|
|
87
|
+
const socketOptions = { type: dgramType };
|
|
60
88
|
if (type === "udp6") {
|
|
61
89
|
socketOptions.ipv6Only = true;
|
|
62
90
|
}
|
|
91
|
+
if (reuseAddress) {
|
|
92
|
+
socketOptions.reuseAddr = true;
|
|
93
|
+
}
|
|
63
94
|
const socket = await createDgramSocket(listeningAddress, listeningPort, socketOptions);
|
|
64
95
|
socket.setBroadcast(true);
|
|
65
96
|
let netInterfaceZone;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/net/NodeJsUdpChannel.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIG;AACP,SAAS,uCAAuC;AAChD,YAAY,WAAW;AACvB,SAAS,qBAAqB;AAE9B,MAAM,SAAS,OAAO,IAAI,eAAe;AAIzC,MAAM,kCAAkC,QAAQ;AAEhD,SAAS,kBAAkB,MAA0B,MAA0B,SAA8B;AACzG,QAAM,SAAS,MAAM,aAAa,OAAO;AACzC,SAAO,IAAI,QAAsB,CAAC,SAAS,WAAW;AAClD,UAAM,kBAAkB,CAAC,UAAiB;AACtC,UAAI;AACA,eAAO,MAAM;AAAA,MACjB,SAASA,QAAO;AACZ,eAAO,MAAM,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["error"]
|
|
6
6
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { HttpEndpoint } from "#general";
|
|
7
|
+
import { IncomingMessage } from "node:http";
|
|
8
|
+
import { Duplex } from "node:stream";
|
|
9
|
+
/**
|
|
10
|
+
* This is a pluggable component that handles the upgrade to a WsConnection.
|
|
11
|
+
*
|
|
12
|
+
* We do not implement directly here because Node.js does not support WebSocket servers natively, so we must use a
|
|
13
|
+
* third-party dependency.
|
|
14
|
+
*/
|
|
15
|
+
export interface WsAdapter {
|
|
16
|
+
handle(req: IncomingMessage, socket: Duplex, head: Buffer): Promise<HttpEndpoint.WsConnection>;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare namespace WsAdapter {
|
|
20
|
+
let defaultFactory: undefined | Factory;
|
|
21
|
+
interface Factory {
|
|
22
|
+
(): WsAdapter;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=WsAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WsAdapter.d.ts","sourceRoot":"","sources":["../../../src/net/WsAdapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACtB,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;IAC/F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,yBAAiB,SAAS,CAAC;IAEhB,IAAI,cAAc,EAAgB,SAAS,GAAG,OAAO,CAAC;IAE7D,UAAiB,OAAO;QACpB,IAAI,SAAS,CAAC;KACjB;CACJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
var WsAdapter;
|
|
7
|
+
((WsAdapter2) => {
|
|
8
|
+
WsAdapter2.defaultFactory = void 0;
|
|
9
|
+
})(WsAdapter || (WsAdapter = {}));
|
|
10
|
+
export {
|
|
11
|
+
WsAdapter
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=WsAdapter.js.map
|
package/dist/esm/net/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Copyright 2022-2025 Matter.js Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
export * from "./NodeJsHttpEndpoint.js";
|
|
6
7
|
export * from "./NodeJsNetwork.js";
|
|
7
8
|
export * from "./NodeJsUdpChannel.js";
|
|
9
|
+
export * from "./WsAdapter.js";
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/net/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/net/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
|
package/dist/esm/net/index.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Copyright 2022-2025 Matter.js Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
export * from "./NodeJsHttpEndpoint.js";
|
|
6
7
|
export * from "./NodeJsNetwork.js";
|
|
7
8
|
export * from "./NodeJsUdpChannel.js";
|
|
9
|
+
export * from "./WsAdapter.js";
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matter/nodejs",
|
|
3
|
-
"version": "0.16.0-alpha.0-
|
|
3
|
+
"version": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
4
4
|
"description": "Node.js platform support for matter.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iot",
|
|
@@ -44,17 +44,17 @@
|
|
|
44
44
|
"#*": "./src/*"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@matter/general": "0.16.0-alpha.0-
|
|
48
|
-
"@matter/node": "0.16.0-alpha.0-
|
|
49
|
-
"@matter/protocol": "0.16.0-alpha.0-
|
|
50
|
-
"@matter/types": "0.16.0-alpha.0-
|
|
47
|
+
"@matter/general": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
48
|
+
"@matter/node": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
49
|
+
"@matter/protocol": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
50
|
+
"@matter/types": "0.16.0-alpha.0-20251013-89bb7099d"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@matter/model": "0.16.0-alpha.0-
|
|
54
|
-
"@matter/protocol": "0.16.0-alpha.0-
|
|
55
|
-
"@matter/
|
|
56
|
-
"@matter/
|
|
57
|
-
"@project-chip/matter.js": "0.16.0-alpha.0-
|
|
53
|
+
"@matter/model": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
54
|
+
"@matter/protocol": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
55
|
+
"@matter/testing": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
56
|
+
"@matter/tools": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
57
|
+
"@project-chip/matter.js": "0.16.0-alpha.0-20251013-89bb7099d",
|
|
58
58
|
"@types/bytebuffer": "^5.0.49"
|
|
59
59
|
},
|
|
60
60
|
"files": [
|
package/src/config.ts
CHANGED
|
@@ -164,7 +164,7 @@ export const config = {
|
|
|
164
164
|
},
|
|
165
165
|
|
|
166
166
|
/**
|
|
167
|
-
* Enables handling of SIGINT, SIGTERM and
|
|
167
|
+
* Enables handling of SIGINT, SIGTERM, SIGUSR2 and SIGABRT (depending on platform; default: true).
|
|
168
168
|
*/
|
|
169
169
|
get trapProcessSignals() {
|
|
170
170
|
return trapProcessSignals;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Boot,
|
|
12
12
|
Crypto,
|
|
13
13
|
Environment,
|
|
14
|
+
HttpEndpointFactory,
|
|
14
15
|
ImplementationError,
|
|
15
16
|
LogFormat,
|
|
16
17
|
Logger,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
StorageService,
|
|
20
21
|
VariableService,
|
|
21
22
|
} from "#general";
|
|
23
|
+
import { NodeJsHttpEndpoint } from "#net/NodeJsHttpEndpoint.js";
|
|
22
24
|
import { existsSync, readFileSync } from "node:fs";
|
|
23
25
|
import { writeFile } from "node:fs/promises";
|
|
24
26
|
import { resolve } from "node:path";
|
|
@@ -65,6 +67,8 @@ import { ProcessManager } from "./ProcessManager.js";
|
|
|
65
67
|
* * `runtime.signals` - By default register SIGINT and SIGUSR2 (diag) handlers, set to false if not wanted
|
|
66
68
|
* * `runtime.exitcode` - By default we set the process.exitcode to 0 (ok) or 1 (crash); set to false to disable
|
|
67
69
|
* * `runtime.unhandlederrors` - By default we log unhandled errors to matter.js log; set to false to disable
|
|
70
|
+
*
|
|
71
|
+
* TODO - this should go away. Node.js services should register with {@link ServiceBundle.default}
|
|
68
72
|
*/
|
|
69
73
|
export function NodeJsEnvironment() {
|
|
70
74
|
const env = new Environment("default");
|
|
@@ -127,6 +131,11 @@ function loadVariables(env: Environment) {
|
|
|
127
131
|
};
|
|
128
132
|
}
|
|
129
133
|
|
|
134
|
+
function rootDirOf(env: Environment) {
|
|
135
|
+
// path.root should always be set when this is called so the "." fallback should not be used
|
|
136
|
+
return env.vars.get("path.root", ".");
|
|
137
|
+
}
|
|
138
|
+
|
|
130
139
|
function configureCrypto(env: Environment) {
|
|
131
140
|
Boot.init(() => {
|
|
132
141
|
if (config.installCrypto || (env.vars.boolean("nodejs.crypto") ?? true)) {
|
|
@@ -144,9 +153,16 @@ function configureNetwork(env: Environment) {
|
|
|
144
153
|
|
|
145
154
|
Boot.init(() => {
|
|
146
155
|
if (config.installNetwork || (env.vars.boolean("nodejs.network") ?? true)) {
|
|
156
|
+
const basePathForUnixSockets = rootDirOf(env);
|
|
147
157
|
env.set(Network, new NodeJsNetwork());
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
env.set(HttpEndpointFactory, new NodeJsHttpEndpoint.Factory(basePathForUnixSockets));
|
|
159
|
+
} else {
|
|
160
|
+
if (Environment.default.has(Network)) {
|
|
161
|
+
env.set(Network, Environment.default.get(Network));
|
|
162
|
+
}
|
|
163
|
+
if (Environment.default.has(HttpEndpointFactory)) {
|
|
164
|
+
env.set(HttpEndpointFactory, Environment.default.get(HttpEndpointFactory));
|
|
165
|
+
}
|
|
150
166
|
}
|
|
151
167
|
});
|
|
152
168
|
}
|
|
@@ -164,11 +180,13 @@ function configureStorage(env: Environment) {
|
|
|
164
180
|
const service = env.get(StorageService);
|
|
165
181
|
|
|
166
182
|
env.vars.use(() => {
|
|
167
|
-
service.location = env.vars.get("storage.path", env
|
|
183
|
+
service.location = env.vars.get("storage.path", rootDirOf(env));
|
|
168
184
|
});
|
|
169
185
|
|
|
170
186
|
service.factory = namespace =>
|
|
171
187
|
new StorageBackendDisk(resolve(service.location ?? ".", namespace), env.vars.get("storage.clear", false));
|
|
188
|
+
|
|
189
|
+
service.resolve = (...paths) => resolve(rootDirOf(env), ...paths);
|
|
172
190
|
}
|
|
173
191
|
|
|
174
192
|
export function loadConfigFile(vars: VariableService) {
|
|
@@ -110,6 +110,16 @@ export class ProcessManager implements Destructable {
|
|
|
110
110
|
this.runtime.interrupt();
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
protected abortHandler = () => {
|
|
114
|
+
this.uninstallInterruptHandlers();
|
|
115
|
+
|
|
116
|
+
logger.fatal("Terminating due to SIGABRT of JS runtime, diagnostics follow");
|
|
117
|
+
logger.info(JSON.stringify(process.report.getReport(), undefined, 2));
|
|
118
|
+
|
|
119
|
+
// Arbitrary code that kind of looks like standard SIGABRT exit code of -6
|
|
120
|
+
process.exit(-66);
|
|
121
|
+
};
|
|
122
|
+
|
|
113
123
|
protected exitHandler = () => {
|
|
114
124
|
if (process.exitCode === 13) {
|
|
115
125
|
logger.error("Internal error: Premature process exit because ongoing work has stalled");
|
|
@@ -123,11 +133,13 @@ export class ProcessManager implements Destructable {
|
|
|
123
133
|
protected installInterruptHandlers = () => {
|
|
124
134
|
process.on("SIGINT", this.interruptHandler);
|
|
125
135
|
process.on("SIGTERM", this.interruptHandler);
|
|
136
|
+
process.on("SIGABRT", this.abortHandler);
|
|
126
137
|
};
|
|
127
138
|
|
|
128
139
|
protected uninstallInterruptHandlers = () => {
|
|
129
140
|
process.off("SIGINT", this.interruptHandler);
|
|
130
141
|
process.off("SIGTERM", this.interruptHandler);
|
|
142
|
+
process.off("SIGABRT", this.abortHandler);
|
|
131
143
|
};
|
|
132
144
|
|
|
133
145
|
#ignoreSignals() {
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { AppAddress, asError, HttpEndpoint, HttpEndpointFactory, Logger, NetworkError } from "#general";
|
|
8
|
+
import { existsSync, ReadStream, rmSync, statSync } from "node:fs";
|
|
9
|
+
import { createServer, IncomingMessage, Server, ServerResponse } from "node:http";
|
|
10
|
+
import { ListenOptions } from "node:net";
|
|
11
|
+
import { normalize, resolve } from "node:path";
|
|
12
|
+
import { Duplex } from "node:stream";
|
|
13
|
+
|
|
14
|
+
// Node's ReadableStream type definition do not exactly match the standard version so we need to import to support casts
|
|
15
|
+
import type { ReadableStream as NodeReadableStream } from "node:stream/web";
|
|
16
|
+
import { WsAdapter } from "./WsAdapter.js";
|
|
17
|
+
|
|
18
|
+
const logger = new Logger("NodeJsHttpEndpoint");
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* An implementation of {@link HttpEndpoint} that uses Node.js's standard {@link Server}.
|
|
22
|
+
*
|
|
23
|
+
* WebSocket support is optional. You can install by importing `@matter/nodejs-ws`.
|
|
24
|
+
*
|
|
25
|
+
* This implementation is a little ugly because the native Node.js HTTP server API is pre-async and has some design
|
|
26
|
+
* flaws. Other runtimes tend build on WinterTC standards and adapters will be much simpler.
|
|
27
|
+
*/
|
|
28
|
+
export class NodeJsHttpEndpoint implements HttpEndpoint {
|
|
29
|
+
#server: Server;
|
|
30
|
+
#ready: Promise<void>;
|
|
31
|
+
#http?: HttpEndpoint.HttpHandler;
|
|
32
|
+
#httpListener?: (req: IncomingMessage, res: ServerResponse) => void;
|
|
33
|
+
#ws?: HttpEndpoint.WsHandler;
|
|
34
|
+
#wsListener?: (req: IncomingMessage, socket: Duplex, head: Buffer) => void;
|
|
35
|
+
#notFound: (res: ServerResponse) => void;
|
|
36
|
+
|
|
37
|
+
#wsAdapter?: WsAdapter;
|
|
38
|
+
#wsAdapterFactory?: WsAdapter.Factory;
|
|
39
|
+
|
|
40
|
+
static async create(options: NodeJsHttpEndpoint.Options): Promise<NodeJsHttpEndpoint> {
|
|
41
|
+
const endpoint = new NodeJsHttpEndpoint(options);
|
|
42
|
+
await endpoint.ready;
|
|
43
|
+
return endpoint;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create a new endpoint.
|
|
48
|
+
*
|
|
49
|
+
* You may pass an existing {@link Server} or pass {@link NodeJsHttpEndpoint.Options} to create a server dedicated
|
|
50
|
+
* to this endpoint.
|
|
51
|
+
*/
|
|
52
|
+
constructor(optionsOrServer: Server | NodeJsHttpEndpoint.Options) {
|
|
53
|
+
let close, ready, server, notFound;
|
|
54
|
+
|
|
55
|
+
if ("on" in optionsOrServer) {
|
|
56
|
+
({ close, ready, server, notFound } = this.#bindToServer(optionsOrServer));
|
|
57
|
+
} else {
|
|
58
|
+
({ close, ready, server, notFound } = this.#createDedicatedServer(optionsOrServer));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.#server = server;
|
|
62
|
+
this.#ready = ready;
|
|
63
|
+
this.close = close;
|
|
64
|
+
this.#notFound = notFound;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get server() {
|
|
68
|
+
return this.#server;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#bindToServer(server: Server) {
|
|
72
|
+
return {
|
|
73
|
+
server,
|
|
74
|
+
ready: Promise.resolve(),
|
|
75
|
+
close: async () => {
|
|
76
|
+
this.http = undefined;
|
|
77
|
+
this.ws = undefined;
|
|
78
|
+
},
|
|
79
|
+
notFound: () => undefined,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#createDedicatedServer(options: NodeJsHttpEndpoint.Options) {
|
|
84
|
+
const server = createServer({ keepAlive: true });
|
|
85
|
+
|
|
86
|
+
const opts = {} as ListenOptions;
|
|
87
|
+
|
|
88
|
+
const address = AppAddress.for(options.address);
|
|
89
|
+
const { transport } = address;
|
|
90
|
+
switch (transport.kind) {
|
|
91
|
+
case "ip":
|
|
92
|
+
if (!address.isWildcardHost) {
|
|
93
|
+
opts.host = address.host;
|
|
94
|
+
}
|
|
95
|
+
if (!address.isWildcardPort) {
|
|
96
|
+
opts.port = address.portNum;
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
|
|
100
|
+
case "unix":
|
|
101
|
+
const path = decodeURIComponent(address.hostname);
|
|
102
|
+
if (options.basePathForUnixSockets) {
|
|
103
|
+
opts.path = resolve(options.basePathForUnixSockets, normalize(path));
|
|
104
|
+
} else {
|
|
105
|
+
opts.path = normalize(path);
|
|
106
|
+
}
|
|
107
|
+
if (existsSync(opts.path)) {
|
|
108
|
+
if (statSync(opts.path).isSocket()) {
|
|
109
|
+
try {
|
|
110
|
+
rmSync(opts.path);
|
|
111
|
+
} catch (e) {
|
|
112
|
+
throw new NetworkError(
|
|
113
|
+
`Error deleting previous socket at ${opts.path}: ${asError(e).message}`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
throw new NetworkError(`UNIX socket path ${opts.path} exists and is not a socket`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
|
|
122
|
+
default:
|
|
123
|
+
throw new NetworkError(
|
|
124
|
+
`Unsupported address type "${(options.address as any)?.type}" for HTTP endpoint`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
server.listen(opts);
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
server,
|
|
132
|
+
|
|
133
|
+
ready: new Promise<void>((resolve, reject) => {
|
|
134
|
+
let settled = false;
|
|
135
|
+
server.once("listening", () => {
|
|
136
|
+
if (settled) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
settled = true;
|
|
141
|
+
resolve();
|
|
142
|
+
});
|
|
143
|
+
server.on("error", error => {
|
|
144
|
+
if (settled) {
|
|
145
|
+
logger.warn("HTTP server error:", error.message);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
settled = true;
|
|
150
|
+
reject(error);
|
|
151
|
+
});
|
|
152
|
+
}),
|
|
153
|
+
|
|
154
|
+
close: async () => {
|
|
155
|
+
return new Promise<void>((resolve, reject) => {
|
|
156
|
+
server.close(err => {
|
|
157
|
+
if (err) {
|
|
158
|
+
reject(err);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
resolve();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
notFound: (res: ServerResponse) => respondError(res, 404),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get ready() {
|
|
172
|
+
return this.#ready;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
set http(handler: HttpEndpoint.HttpHandler | undefined) {
|
|
176
|
+
this.#http = handler;
|
|
177
|
+
|
|
178
|
+
if (!this.#http) {
|
|
179
|
+
if (this.#httpListener) {
|
|
180
|
+
this.#server.off("request", this.#httpListener);
|
|
181
|
+
}
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (this.#httpListener) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
this.#httpListener = (req, res) => {
|
|
190
|
+
this.#handleHttp(req, res).catch(error => {
|
|
191
|
+
logger.error("Unhandled error in HTTP endpoint handler", error);
|
|
192
|
+
respondError(res, 500);
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
this.#server.on("request", this.#httpListener);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
set ws(handler: HttpEndpoint.WsHandler | undefined) {
|
|
200
|
+
this.#ws = handler;
|
|
201
|
+
|
|
202
|
+
if (!this.#ws) {
|
|
203
|
+
if (this.#wsListener) {
|
|
204
|
+
this.#server.off("upgrade", this.#wsListener);
|
|
205
|
+
}
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let adapter = this.#wsAdapter;
|
|
210
|
+
if (!adapter) {
|
|
211
|
+
const factory = this.#wsAdapterFactory ?? WsAdapter.defaultFactory;
|
|
212
|
+
if (!factory) {
|
|
213
|
+
logger.warn(
|
|
214
|
+
"WebSocket support disabled because no adapter is installed; please import @matter/nodejs-ws or equivalent",
|
|
215
|
+
);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
adapter = this.#wsAdapter = factory();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
this.#wsListener = (req, socket, head) => {
|
|
222
|
+
this.#handleUpgrade(adapter, req, socket, head).catch(error => {
|
|
223
|
+
logger.error("Unhandled error WebSocket endpoint", error);
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
this.#server.on("upgrade", this.#wsListener);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
close: () => Promise<void>;
|
|
231
|
+
|
|
232
|
+
async #handleHttp(req: IncomingMessage, res: ServerResponse) {
|
|
233
|
+
if (!this.#http) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const request = new NodeJsHttpRequest(req);
|
|
238
|
+
|
|
239
|
+
const response = await this.#http(request);
|
|
240
|
+
if (!response) {
|
|
241
|
+
this.#notFound(res);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
res.statusCode = response.status;
|
|
246
|
+
res.statusMessage = response.statusText;
|
|
247
|
+
|
|
248
|
+
response.headers.forEach(([name, value]) => res.appendHeader(name, value));
|
|
249
|
+
|
|
250
|
+
if (response.body === null) {
|
|
251
|
+
res.end();
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const nodeBodyStream = ReadStream.fromWeb(response.body as NodeReadableStream);
|
|
256
|
+
|
|
257
|
+
nodeBodyStream.on("error", error => {
|
|
258
|
+
logger.error("Error transmitting HTTP body", error);
|
|
259
|
+
respondError(res, 500);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
nodeBodyStream.pipe(res);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async #handleUpgrade(adapter: WsAdapter, req: IncomingMessage, socket: Duplex, head: Buffer) {
|
|
266
|
+
if (req.headers.upgrade !== "websocket") {
|
|
267
|
+
// Not clear how to send a 426 with Node's API
|
|
268
|
+
socket.destroy();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// This shouldn't happen
|
|
273
|
+
if (!this.#ws) {
|
|
274
|
+
socket.destroy();
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const request = new NodeJsHttpRequest(req);
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
await this.#ws(request, async () => {
|
|
282
|
+
return adapter.handle(req, socket, head);
|
|
283
|
+
});
|
|
284
|
+
} finally {
|
|
285
|
+
// Node API is fairly broken and offers no way to indicate we've skipped the socket so we must destroy it
|
|
286
|
+
// if not already handled
|
|
287
|
+
if (!socket.destroyed) {
|
|
288
|
+
socket.destroy();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
class NodeJsHttpRequest extends Request {
|
|
295
|
+
constructor(message: IncomingMessage) {
|
|
296
|
+
const { method, rawHeaders } = message;
|
|
297
|
+
|
|
298
|
+
const url = `http://${message.headers.host ?? "unknown"}${message.url ?? "/"}`;
|
|
299
|
+
|
|
300
|
+
const headers = new Headers();
|
|
301
|
+
|
|
302
|
+
for (let i = 0; i < message.rawHeaders.length; i += 2) {
|
|
303
|
+
headers.append(rawHeaders[i], rawHeaders[i + 1]);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const init = {
|
|
307
|
+
method,
|
|
308
|
+
headers,
|
|
309
|
+
duplex: "half", // Not in RequestInit type but required by node
|
|
310
|
+
} as RequestInit;
|
|
311
|
+
|
|
312
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
313
|
+
init.body = IncomingMessage.toWeb(message) as ReadableStream;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
super(url, init);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function respondError(res: ServerResponse, code: number) {
|
|
321
|
+
if (res.closed) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
if (!res.headersSent) {
|
|
327
|
+
res.statusCode = code;
|
|
328
|
+
res.setHeader("Content-Type", "text/plain");
|
|
329
|
+
res.end(`HTTP error ${code}\n`);
|
|
330
|
+
} else {
|
|
331
|
+
res.end();
|
|
332
|
+
}
|
|
333
|
+
} catch (e) {
|
|
334
|
+
logger.warn(`Error conveying ${code} error:`, asError(e).message);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export namespace NodeJsHttpEndpoint {
|
|
339
|
+
export interface Options extends HttpEndpoint.Options {
|
|
340
|
+
basePathForUnixSockets?: string;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export class Factory extends HttpEndpointFactory {
|
|
344
|
+
#basePathForUnixSockets?: string;
|
|
345
|
+
|
|
346
|
+
constructor(basePathForUnixSockets?: string) {
|
|
347
|
+
super();
|
|
348
|
+
this.#basePathForUnixSockets = basePathForUnixSockets;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async create(options: HttpEndpoint.Options) {
|
|
352
|
+
return NodeJsHttpEndpoint.create({
|
|
353
|
+
basePathForUnixSockets: this.#basePathForUnixSockets,
|
|
354
|
+
...options,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|