oox 0.3.3 → 0.3.5
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 +13 -0
- package/app.js +1 -1
- package/bin/cli.js +75 -15
- package/bin/configurer.js +6 -9
- package/bin/register.js +48 -15
- package/bin/starter.js +8 -0
- package/config.js +116 -0
- package/index.js +70 -44
- package/{rpc-keepalive-connection.js → keepalive-connection.js} +36 -16
- package/modules/http/index.js +52 -63
- package/modules/http/router.js +9 -4
- package/modules/index.js +78 -74
- package/modules/module.js +0 -9
- package/modules/socketio/adapter.js +30 -139
- package/modules/socketio/server.js +37 -38
- package/modules/socketio/utils.js +5 -2
- package/package.json +10 -4
- package/registry.js +145 -0
- package/samples/index.js +1 -0
- package/samples/keepalive-connection-sample.js +147 -0
- package/types/app.d.ts +20 -20
- package/types/bin/configurer.d.ts +3 -1
- package/types/bin/register.d.ts +2 -1
- package/types/bin/starter.d.ts +1 -2
- package/types/config.d.ts +54 -0
- package/types/index.d.ts +37 -31
- package/types/keepalive-connection.d.ts +104 -0
- package/types/modules/http/index.d.ts +4 -7
- package/types/modules/index.d.ts +36 -21
- package/types/modules/module.d.ts +9 -9
- package/types/modules/socketio/adapter.d.ts +10 -24
- package/types/modules/socketio/server.d.ts +6 -10
- package/types/modules/socketio/utils.d.ts +5 -2
- package/types/registry.d.ts +41 -0
- package/types/samples/index.d.ts +1 -0
- package/types/samples/keepalive-connection-sample.d.ts +55 -0
- package/utils.js +1 -1
- package/types/rpc-keepalive-connection.d.ts +0 -57
package/modules/http/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as http from 'node:http';
|
|
2
2
|
import * as https from 'node:https';
|
|
3
|
-
import {
|
|
3
|
+
import { parseHTTPBody } from './utils.js';
|
|
4
4
|
import Router from './router.js';
|
|
5
5
|
import * as oox from '../../index.js';
|
|
6
|
-
import Module
|
|
7
|
-
export class HTTPConfig
|
|
6
|
+
import Module from '../module.js';
|
|
7
|
+
export class HTTPConfig {
|
|
8
|
+
enabled = true;
|
|
8
9
|
// listen port
|
|
9
10
|
port = 0;
|
|
10
11
|
// service path
|
|
@@ -80,9 +81,9 @@ export default class HTTPModule extends Module {
|
|
|
80
81
|
if (ssl.enabled) {
|
|
81
82
|
const fs = await import('node:fs');
|
|
82
83
|
const options = {
|
|
83
|
-
key: ssl.key ? fs.readFileSync(ssl.key) :
|
|
84
|
-
cert: ssl.cert ? fs.readFileSync(ssl.cert) :
|
|
85
|
-
ca: ssl.ca ? fs.readFileSync(ssl.ca) :
|
|
84
|
+
key: ssl.key ? fs.readFileSync(ssl.key) : undefined,
|
|
85
|
+
cert: ssl.cert ? fs.readFileSync(ssl.cert) : undefined,
|
|
86
|
+
ca: ssl.ca ? fs.readFileSync(ssl.ca) : undefined
|
|
86
87
|
};
|
|
87
88
|
if (!options.key || !options.cert) {
|
|
88
89
|
throw new Error('HTTPS enabled but missing key or cert');
|
|
@@ -101,16 +102,18 @@ export default class HTTPModule extends Module {
|
|
|
101
102
|
/**
|
|
102
103
|
* stop http service
|
|
103
104
|
*/
|
|
104
|
-
stop() {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
async stop() {
|
|
106
|
+
const { server } = this;
|
|
107
|
+
if (!server || !server.listening)
|
|
108
|
+
return Promise.resolve();
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
server.close(function (error) {
|
|
111
|
+
if (error)
|
|
112
|
+
reject(error);
|
|
113
|
+
else
|
|
114
|
+
resolve();
|
|
113
115
|
});
|
|
116
|
+
});
|
|
114
117
|
}
|
|
115
118
|
/**
|
|
116
119
|
* browser cross origin
|
|
@@ -120,9 +123,14 @@ export default class HTTPModule extends Module {
|
|
|
120
123
|
const origin = this.config.origin;
|
|
121
124
|
const requestOrigin = request.headers.origin;
|
|
122
125
|
if (origin && requestOrigin) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
let allow = false;
|
|
127
|
+
if ('string' === typeof origin) {
|
|
128
|
+
allow = origin === '*' || new RegExp(origin).test(requestOrigin);
|
|
129
|
+
}
|
|
130
|
+
else if (Array.isArray(origin)) {
|
|
131
|
+
allow = origin.some(item => item === '*' || new RegExp(item).test(requestOrigin));
|
|
132
|
+
}
|
|
133
|
+
if (allow) {
|
|
126
134
|
response.setHeader('Access-Control-Allow-Origin', requestOrigin);
|
|
127
135
|
response.setHeader('Vary', 'Origin');
|
|
128
136
|
}
|
|
@@ -132,7 +140,7 @@ export default class HTTPModule extends Module {
|
|
|
132
140
|
return false;
|
|
133
141
|
}
|
|
134
142
|
response.setHeader('Access-Control-Max-Age', 3600);
|
|
135
|
-
response.setHeader('Access-Control-Allow-Headers', 'x-caller,content-type');
|
|
143
|
+
response.setHeader('Access-Control-Allow-Headers', 'x-caller,x-token,content-type');
|
|
136
144
|
response.setHeader('Access-Control-Allow-Methods', '*');
|
|
137
145
|
}
|
|
138
146
|
if (request.method === 'OPTIONS') {
|
|
@@ -143,9 +151,7 @@ export default class HTTPModule extends Module {
|
|
|
143
151
|
return true;
|
|
144
152
|
}
|
|
145
153
|
async requestHandler(request, response) {
|
|
146
|
-
|
|
147
|
-
return;
|
|
148
|
-
const url = new URL(request.url, `http://${request.headers.host || 'localhost'}`);
|
|
154
|
+
const url = new URL(request.url || '', `http://${request.headers.host || 'localhost'}`);
|
|
149
155
|
const method = request.method || 'GET';
|
|
150
156
|
// 尝试匹配路由
|
|
151
157
|
const matched = this.router.match(method, url.pathname);
|
|
@@ -170,6 +176,9 @@ export default class HTTPModule extends Module {
|
|
|
170
176
|
await this.router.handleRoute(matched.route, matched.params, req, res);
|
|
171
177
|
return;
|
|
172
178
|
}
|
|
179
|
+
// 内置cors仅处理RPC请求
|
|
180
|
+
if (!this.cors(request, response))
|
|
181
|
+
return;
|
|
173
182
|
// 回退到RPC调用
|
|
174
183
|
if (url.pathname === this.config.path) {
|
|
175
184
|
await this.call(request, response);
|
|
@@ -199,6 +208,24 @@ export default class HTTPModule extends Module {
|
|
|
199
208
|
* HTTP-RPC服务器请求监听方法
|
|
200
209
|
*/
|
|
201
210
|
async call(request, response) {
|
|
211
|
+
// global unique id
|
|
212
|
+
const traceId = String(request.headers['x-trace-id'] || '');
|
|
213
|
+
// service name, required
|
|
214
|
+
const caller = String(request.headers['x-caller'] || 'anonymous');
|
|
215
|
+
// client ip or caller service ip
|
|
216
|
+
const ip = String(request.headers['x-real-ip'] || request.socket.remoteAddress || '');
|
|
217
|
+
// startup client ip
|
|
218
|
+
const sourceIP = String(request.headers['x-source-ip'] || request.socket.remoteAddress || '');
|
|
219
|
+
// check token
|
|
220
|
+
const token = String(request.headers['x-token'] || '');
|
|
221
|
+
const { allow, reason } = oox.checkAllow(ip, caller, token);
|
|
222
|
+
if (!allow)
|
|
223
|
+
return this.respond(request, response, {
|
|
224
|
+
success: false,
|
|
225
|
+
error: {
|
|
226
|
+
message: reason
|
|
227
|
+
}
|
|
228
|
+
});
|
|
202
229
|
let callArgs = Object.create(null);
|
|
203
230
|
try {
|
|
204
231
|
callArgs = await this.getCallArgsFromRequest(request);
|
|
@@ -212,14 +239,6 @@ export default class HTTPModule extends Module {
|
|
|
212
239
|
}
|
|
213
240
|
});
|
|
214
241
|
}
|
|
215
|
-
// global unique id
|
|
216
|
-
const traceId = String(request.headers['x-trace-id'] || '');
|
|
217
|
-
// service name, required
|
|
218
|
-
const caller = String(request.headers['x-caller'] || 'anonymous');
|
|
219
|
-
// client ip or caller service ip
|
|
220
|
-
const ip = String(request.headers['x-ip'] || request.socket.remoteAddress || '');
|
|
221
|
-
// startup client ip
|
|
222
|
-
const sourceIP = String(request.headers['x-real-ip'] || '');
|
|
223
242
|
const { action, params = [] } = callArgs;
|
|
224
243
|
const context = oox.genContext({ traceId, caller, sourceIP, ip, callerId: '' });
|
|
225
244
|
const format = await oox.call(action, params, context);
|
|
@@ -237,15 +256,15 @@ export default class HTTPModule extends Module {
|
|
|
237
256
|
try {
|
|
238
257
|
returnsString = JSON.stringify(returns);
|
|
239
258
|
}
|
|
240
|
-
catch (
|
|
259
|
+
catch (error) {
|
|
241
260
|
delete returns.body;
|
|
242
261
|
returns.success = false;
|
|
243
262
|
returns.error = {
|
|
244
|
-
message
|
|
263
|
+
message: error.message
|
|
245
264
|
};
|
|
246
265
|
if (oox.config.errorStack) {
|
|
247
266
|
// 返回错误调用栈信息
|
|
248
|
-
returns.error.stack = stack;
|
|
267
|
+
returns.error.stack = error.stack;
|
|
249
268
|
}
|
|
250
269
|
returnsString = JSON.stringify(returns);
|
|
251
270
|
}
|
|
@@ -253,34 +272,4 @@ export default class HTTPModule extends Module {
|
|
|
253
272
|
response.setHeader('Content-Length', Buffer.byteLength(returnsString));
|
|
254
273
|
response.end(returnsString);
|
|
255
274
|
}
|
|
256
|
-
/**
|
|
257
|
-
* HTTP RPC
|
|
258
|
-
*/
|
|
259
|
-
async rpc(url, action, params, context) {
|
|
260
|
-
if (!context || !context.traceId) {
|
|
261
|
-
context = oox.getContext();
|
|
262
|
-
}
|
|
263
|
-
const { traceId, caller, sourceIP } = context;
|
|
264
|
-
const headers = {
|
|
265
|
-
'Content-Type': 'application/json',
|
|
266
|
-
'x-trace-id': String(traceId),
|
|
267
|
-
};
|
|
268
|
-
if (caller)
|
|
269
|
-
headers['x-caller'] = String(caller);
|
|
270
|
-
if (sourceIP)
|
|
271
|
-
headers['x-real-ip'] = sourceIP;
|
|
272
|
-
// headers [ 'x-ip' ] = getIPAddress ( 4 ) [ 0 ]
|
|
273
|
-
const format = await httpRequest(url, {
|
|
274
|
-
headers
|
|
275
|
-
}, JSON.stringify({ action, params }));
|
|
276
|
-
if ('string' === typeof format)
|
|
277
|
-
throw new Error(format);
|
|
278
|
-
const { success, error, body } = format;
|
|
279
|
-
if (success)
|
|
280
|
-
return body;
|
|
281
|
-
else if (error)
|
|
282
|
-
throw new Error(error.message);
|
|
283
|
-
else
|
|
284
|
-
throw new Error('[RPC] Unknown Error');
|
|
285
|
-
}
|
|
286
275
|
}
|
package/modules/http/router.js
CHANGED
|
@@ -84,12 +84,17 @@ export default class Router {
|
|
|
84
84
|
}
|
|
85
85
|
// 添加路由
|
|
86
86
|
addRoute(method, path, handler, middleware = []) {
|
|
87
|
-
if (!this.routes.has(method)) {
|
|
88
|
-
this.routes.set(method, []);
|
|
89
|
-
}
|
|
90
87
|
// 编译路径为正则表达式,支持路径参数
|
|
91
88
|
const { regex, paramNames } = this.compilePath(path);
|
|
92
|
-
|
|
89
|
+
let routes = [];
|
|
90
|
+
if (this.routes.has(method)) {
|
|
91
|
+
routes = this.routes.get(method) || [];
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
routes = [];
|
|
95
|
+
this.routes.set(method, routes);
|
|
96
|
+
}
|
|
97
|
+
routes.push({
|
|
93
98
|
path,
|
|
94
99
|
method,
|
|
95
100
|
handler,
|
package/modules/index.js
CHANGED
|
@@ -1,86 +1,90 @@
|
|
|
1
|
-
import Module from './module.js';
|
|
2
1
|
import HTTP from './http/index.js';
|
|
3
2
|
import SocketIO from './socketio/index.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.#map.delete(name);
|
|
49
|
-
}
|
|
50
|
-
setConfig(config) {
|
|
51
|
-
for (const module of this.#queue) {
|
|
52
|
-
if (module.name in config) {
|
|
53
|
-
const moduleConfig = config[module.name];
|
|
54
|
-
if ('boolean' === typeof moduleConfig) {
|
|
55
|
-
// eg: http=yes/no
|
|
56
|
-
module.setConfig({ enabled: moduleConfig });
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
module.setConfig(moduleConfig);
|
|
60
|
-
}
|
|
3
|
+
/**
|
|
4
|
+
* FIFO queue for modules starting
|
|
5
|
+
*/
|
|
6
|
+
export const queue = [];
|
|
7
|
+
/**
|
|
8
|
+
* all modules map
|
|
9
|
+
*/
|
|
10
|
+
export const map = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* add module to modules queue
|
|
13
|
+
*/
|
|
14
|
+
export function add(module) {
|
|
15
|
+
if (!module.name || 'string' !== typeof module.name)
|
|
16
|
+
throw new Error(`Module<${module.name}> has noname`);
|
|
17
|
+
if (map.has(module.name))
|
|
18
|
+
throw new Error(`Module<${module.name}> has exists`);
|
|
19
|
+
map.set(module.name, module);
|
|
20
|
+
queue.push(module);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* get module by name
|
|
24
|
+
*/
|
|
25
|
+
export function get(name) {
|
|
26
|
+
return map.get(name) || null;
|
|
27
|
+
}
|
|
28
|
+
export async function remove(name) {
|
|
29
|
+
const module = map.get(name);
|
|
30
|
+
if (!module)
|
|
31
|
+
return;
|
|
32
|
+
await module.stop();
|
|
33
|
+
const index = queue.indexOf(module);
|
|
34
|
+
queue.splice(index, 1);
|
|
35
|
+
map.delete(name);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* set modules config
|
|
39
|
+
*/
|
|
40
|
+
export function setConfig(config) {
|
|
41
|
+
for (const module of queue) {
|
|
42
|
+
if (module.name in config) {
|
|
43
|
+
const moduleConfig = config[module.name];
|
|
44
|
+
if ('boolean' === typeof moduleConfig) {
|
|
45
|
+
// eg: http=yes/no
|
|
46
|
+
module.setConfig({ enabled: moduleConfig });
|
|
61
47
|
}
|
|
62
48
|
else {
|
|
63
|
-
module.setConfig(
|
|
49
|
+
module.setConfig(moduleConfig);
|
|
64
50
|
}
|
|
65
|
-
config[module.name] = module.getConfig();
|
|
66
51
|
}
|
|
52
|
+
else {
|
|
53
|
+
module.setConfig({ enabled: true });
|
|
54
|
+
}
|
|
55
|
+
config[module.name] = module.getConfig();
|
|
67
56
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* serve modules
|
|
60
|
+
*/
|
|
61
|
+
export async function serve() {
|
|
62
|
+
try {
|
|
63
|
+
for (const module of queue) {
|
|
64
|
+
if (module.getConfig().enabled) {
|
|
65
|
+
await module.serve();
|
|
74
66
|
}
|
|
75
67
|
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
await this.stop();
|
|
78
|
-
throw error;
|
|
79
|
-
}
|
|
80
68
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
69
|
+
catch (error) {
|
|
70
|
+
await stop();
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* stop all modules
|
|
76
|
+
*/
|
|
77
|
+
export async function stop() {
|
|
78
|
+
for (const module of queue) {
|
|
79
|
+
await module.stop();
|
|
85
80
|
}
|
|
86
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* all builtin modules
|
|
84
|
+
*/
|
|
85
|
+
export const builtins = {
|
|
86
|
+
http: new HTTP,
|
|
87
|
+
socketio: new SocketIO,
|
|
88
|
+
};
|
|
89
|
+
add(builtins.http);
|
|
90
|
+
add(builtins.socketio);
|
package/modules/module.js
CHANGED
|
@@ -1,158 +1,49 @@
|
|
|
1
1
|
import * as SocketIOClient from 'socket.io-client';
|
|
2
2
|
import * as oox from '../../index.js';
|
|
3
|
-
import { OOXEvent, genWebSocketURL
|
|
3
|
+
import { OOXEvent, genWebSocketURL } from './utils.js';
|
|
4
4
|
import { randomUUID } from 'node:crypto';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (data.name === oox.config.name)
|
|
13
|
-
continue;
|
|
14
|
-
if (!data.url || !isWebSocketURL(data.url))
|
|
15
|
-
continue;
|
|
16
|
-
const has = oox.keepAliveConnections.has(data.name, data.id);
|
|
17
|
-
if (has)
|
|
18
|
-
continue;
|
|
19
|
-
this.open(data.url).catch((error) => console.error(error));
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
bindClientConnectionEvents(connection) {
|
|
23
|
-
const socket = connection.nativeConnection;
|
|
24
|
-
socket.on(OOXEvent.CONNECTED, ({ id, name }) => {
|
|
25
|
-
connection.updateIdAndName(id, name);
|
|
26
|
-
connection.enabled = true;
|
|
27
|
-
socket.emit(OOXEvent.SYNC_CONNECTIONS, this[OOXEvent.SYNC_CONNECTIONS].bind(this));
|
|
28
|
-
});
|
|
29
|
-
socket.on(OOXEvent.DISABLED, () => {
|
|
30
|
-
connection.enabled = false;
|
|
31
|
-
});
|
|
32
|
-
socket.on('disconnect', (reason) => {
|
|
33
|
-
connection.emit('disconnect');
|
|
34
|
-
oox.removeKeepAliveConnection(connection);
|
|
35
|
-
socket.removeAllListeners();
|
|
36
|
-
socket.disconnect();
|
|
37
|
-
});
|
|
38
|
-
socket.on('connect', () => {
|
|
39
|
-
connection.emit('connect');
|
|
40
|
-
});
|
|
41
|
-
socket.on('connect_error', (error) => {
|
|
42
|
-
connection.emit('error', error);
|
|
43
|
-
oox.removeKeepAliveConnection(connection);
|
|
44
|
-
socket.removeAllListeners();
|
|
45
|
-
socket.disconnect();
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
newConnection(url) {
|
|
49
|
-
const { id, host, name } = oox.config;
|
|
5
|
+
import { SampleKeepAliveConnectionAdapter } from '../../samples/index.js';
|
|
6
|
+
export default class SocketIOAdapter extends SampleKeepAliveConnectionAdapter {
|
|
7
|
+
name = 'socketio';
|
|
8
|
+
OOXEvent = OOXEvent;
|
|
9
|
+
nativeEvent = { CONNECT: 'connect', DISCONNECT: 'disconnect', ERROR: 'connect_error' };
|
|
10
|
+
newConnection(identify) {
|
|
11
|
+
const { id, name } = oox.config;
|
|
50
12
|
const headers = {
|
|
51
|
-
'x-ip': host,
|
|
52
13
|
'x-caller': name,
|
|
53
14
|
'x-caller-id': id,
|
|
54
15
|
};
|
|
55
16
|
let mURL;
|
|
56
|
-
|
|
57
|
-
|
|
17
|
+
const connectionData = {
|
|
18
|
+
name: 'anonymous',
|
|
19
|
+
id: randomUUID(),
|
|
20
|
+
adapter: this.name,
|
|
21
|
+
ip: '',
|
|
22
|
+
token: ''
|
|
23
|
+
};
|
|
24
|
+
if ('string' === typeof identify) {
|
|
25
|
+
mURL = genWebSocketURL(identify);
|
|
26
|
+
}
|
|
27
|
+
else if (identify instanceof URL) {
|
|
28
|
+
mURL = identify;
|
|
29
|
+
}
|
|
30
|
+
else if (identify.url) {
|
|
31
|
+
// KeepAliveConnectionData
|
|
32
|
+
Object.assign(connectionData, identify);
|
|
33
|
+
mURL = new URL(identify.url);
|
|
34
|
+
if (identify.token) {
|
|
35
|
+
headers['x-token'] = identify.token;
|
|
36
|
+
}
|
|
58
37
|
}
|
|
59
38
|
else {
|
|
60
|
-
|
|
39
|
+
throw new Error('identify must be string, URL, or KeepAliveConnectionData');
|
|
61
40
|
}
|
|
62
41
|
const socket = SocketIOClient.io(mURL.origin, {
|
|
63
42
|
extraHeaders: headers,
|
|
64
43
|
path: mURL.pathname,
|
|
65
44
|
autoConnect: false,
|
|
66
45
|
});
|
|
67
|
-
const
|
|
68
|
-
name: 'anonymous',
|
|
69
|
-
id: randomUUID(),
|
|
70
|
-
host: mURL.host,
|
|
71
|
-
url: mURL
|
|
72
|
-
};
|
|
73
|
-
const connection = new oox.RPCKeepAliveConnection(this, socket, data);
|
|
74
|
-
return connection;
|
|
75
|
-
}
|
|
76
|
-
async open(url) {
|
|
77
|
-
const connection = this.newConnection(url);
|
|
78
|
-
oox.addKeepAliveConnection(connection);
|
|
79
|
-
this.bindClientConnectionEvents(connection);
|
|
80
|
-
this.bindCall(connection);
|
|
81
|
-
await new Promise((resolve, reject) => {
|
|
82
|
-
connection.once('enabled', resolve);
|
|
83
|
-
connection.once('error', reject);
|
|
84
|
-
connection.once('disconnect', () => {
|
|
85
|
-
reject(new Error('disconnect'));
|
|
86
|
-
});
|
|
87
|
-
connection.nativeConnection.connect();
|
|
88
|
-
});
|
|
46
|
+
const connection = new oox.KeepAliveConnection(this, socket, connectionData);
|
|
89
47
|
return connection;
|
|
90
48
|
}
|
|
91
|
-
async close(connection) {
|
|
92
|
-
connection.nativeConnection.disconnect();
|
|
93
|
-
return Promise.resolve();
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* socketio emit
|
|
97
|
-
*/
|
|
98
|
-
async emit(socket, event, params) {
|
|
99
|
-
if (!socket.connected)
|
|
100
|
-
throw new Error('Socket not connected');
|
|
101
|
-
return await new Promise((resolve, reject) => {
|
|
102
|
-
const onError = (reason) => {
|
|
103
|
-
const message = 'string' === typeof reason ? reason : reason instanceof Error ? reason.message : 'connect error';
|
|
104
|
-
reject(new Error(message));
|
|
105
|
-
};
|
|
106
|
-
// RPC 执行时中断连接
|
|
107
|
-
socket.once('disconnect', onError);
|
|
108
|
-
socket.emit(event, ...params, (returns) => {
|
|
109
|
-
socket.offAny(onError);
|
|
110
|
-
resolve(returns);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* RPC
|
|
116
|
-
*/
|
|
117
|
-
async rpc(connection, action, params, context) {
|
|
118
|
-
if (!context)
|
|
119
|
-
context = oox.getContext();
|
|
120
|
-
const { success, error, body } = await this.emit(connection.nativeConnection, 'call', [action, params, context]);
|
|
121
|
-
if (success)
|
|
122
|
-
return body;
|
|
123
|
-
else if (error)
|
|
124
|
-
throw new Error(error.message);
|
|
125
|
-
else
|
|
126
|
-
throw new Error('[RPC] Unknown Error');
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* 绑定 call 事件
|
|
130
|
-
* @param connection
|
|
131
|
-
*/
|
|
132
|
-
bindCall(connection) {
|
|
133
|
-
const { id, name, host } = connection.data;
|
|
134
|
-
const connectionContext = {
|
|
135
|
-
sourceIP: '',
|
|
136
|
-
ip: host,
|
|
137
|
-
caller: name,
|
|
138
|
-
callerId: id,
|
|
139
|
-
connection
|
|
140
|
-
};
|
|
141
|
-
connection.nativeConnection.on('call', async (action, params, context, callback) => {
|
|
142
|
-
if ('object' !== typeof context)
|
|
143
|
-
context = oox.genContext(connectionContext);
|
|
144
|
-
else
|
|
145
|
-
context = oox.genContext(Object.assign(context, connectionContext));
|
|
146
|
-
this.call(action, params, context, callback);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
async call(action, params, context, callback) {
|
|
150
|
-
const returns = await oox.call(action, params, context);
|
|
151
|
-
if (returns.error && !oox.config.errorStack) {
|
|
152
|
-
// 不返回错误调用栈信息
|
|
153
|
-
delete returns.error.stack;
|
|
154
|
-
}
|
|
155
|
-
'function' === typeof callback && callback(returns);
|
|
156
|
-
return returns;
|
|
157
|
-
}
|
|
158
49
|
}
|