oox 0.3.4 → 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 +45 -12
- 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 +67 -46
- package/keepalive-connection.js +13 -0
- 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 +24 -12
- package/modules/socketio/server.js +33 -15
- package/modules/socketio/utils.js +3 -1
- package/package.json +9 -5
- package/registry.js +90 -6
- package/samples/keepalive-connection-sample.js +40 -23
- 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 +34 -31
- package/types/keepalive-connection.d.ts +40 -15
- 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 +1 -1
- package/types/modules/socketio/server.d.ts +5 -3
- package/types/modules/socketio/utils.d.ts +3 -1
- package/types/registry.d.ts +28 -3
- package/types/samples/keepalive-connection-sample.d.ts +20 -11
- package/utils.js +1 -1
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
|
@@ -7,31 +7,43 @@ export default class SocketIOAdapter extends SampleKeepAliveConnectionAdapter {
|
|
|
7
7
|
name = 'socketio';
|
|
8
8
|
OOXEvent = OOXEvent;
|
|
9
9
|
nativeEvent = { CONNECT: 'connect', DISCONNECT: 'disconnect', ERROR: 'connect_error' };
|
|
10
|
-
newConnection(
|
|
11
|
-
const { id,
|
|
10
|
+
newConnection(identify) {
|
|
11
|
+
const { id, name } = oox.config;
|
|
12
12
|
const headers = {
|
|
13
|
-
'x-ip': host,
|
|
14
13
|
'x-caller': name,
|
|
15
14
|
'x-caller-id': id,
|
|
16
15
|
};
|
|
17
16
|
let mURL;
|
|
18
|
-
|
|
19
|
-
|
|
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
|
+
}
|
|
20
37
|
}
|
|
21
38
|
else {
|
|
22
|
-
|
|
39
|
+
throw new Error('identify must be string, URL, or KeepAliveConnectionData');
|
|
23
40
|
}
|
|
24
41
|
const socket = SocketIOClient.io(mURL.origin, {
|
|
25
42
|
extraHeaders: headers,
|
|
26
43
|
path: mURL.pathname,
|
|
27
44
|
autoConnect: false,
|
|
28
45
|
});
|
|
29
|
-
const connection = new oox.KeepAliveConnection(this, socket,
|
|
30
|
-
name: 'anonymous',
|
|
31
|
-
id: randomUUID(),
|
|
32
|
-
host: mURL.host,
|
|
33
|
-
url: mURL
|
|
34
|
-
});
|
|
46
|
+
const connection = new oox.KeepAliveConnection(this, socket, connectionData);
|
|
35
47
|
return connection;
|
|
36
48
|
}
|
|
37
49
|
}
|
|
@@ -2,10 +2,11 @@ import * as http from 'node:http';
|
|
|
2
2
|
import * as https from 'node:https';
|
|
3
3
|
import { Server } from 'socket.io';
|
|
4
4
|
import * as oox from '../../index.js';
|
|
5
|
-
import { Module
|
|
5
|
+
import { Module } from '../../index.js';
|
|
6
6
|
import SocketIOAdapter from './adapter.js';
|
|
7
7
|
import { OOXEvent } from './utils.js';
|
|
8
|
-
export class SocketIOConfig
|
|
8
|
+
export class SocketIOConfig {
|
|
9
|
+
enabled = true;
|
|
9
10
|
// listen port
|
|
10
11
|
port = 0;
|
|
11
12
|
// service path
|
|
@@ -34,6 +35,10 @@ export default class SocketIOServer extends Module {
|
|
|
34
35
|
server = null;
|
|
35
36
|
socketServer = null;
|
|
36
37
|
adapter = new SocketIOAdapter();
|
|
38
|
+
constructor() {
|
|
39
|
+
super();
|
|
40
|
+
oox.keepAliveConnectionAdapters.set(this.name, this.adapter);
|
|
41
|
+
}
|
|
37
42
|
getURL() {
|
|
38
43
|
const { host } = oox.config;
|
|
39
44
|
const { port, path } = this.config;
|
|
@@ -53,21 +58,22 @@ export default class SocketIOServer extends Module {
|
|
|
53
58
|
return this.config;
|
|
54
59
|
}
|
|
55
60
|
async serve() {
|
|
56
|
-
oox.keepAliveConnectionAdapters.set(this.name, this.adapter);
|
|
57
61
|
await this.stop();
|
|
58
62
|
const { port, ssl } = this.config;
|
|
59
63
|
const isSelfServer = this.#isSelfServer = this.server ? true : false;
|
|
60
|
-
let server;
|
|
64
|
+
let server = null;
|
|
61
65
|
if (isSelfServer) {
|
|
66
|
+
if (!this.server)
|
|
67
|
+
throw new Error('HTTP Server is not created');
|
|
62
68
|
server = this.server;
|
|
63
69
|
}
|
|
64
70
|
else {
|
|
65
71
|
if (ssl.enabled) {
|
|
66
72
|
const fs = await import('node:fs');
|
|
67
73
|
const options = {
|
|
68
|
-
key: ssl.key ? fs.readFileSync(ssl.key) :
|
|
69
|
-
cert: ssl.cert ? fs.readFileSync(ssl.cert) :
|
|
70
|
-
ca: ssl.ca ? fs.readFileSync(ssl.ca) :
|
|
74
|
+
key: ssl.key ? fs.readFileSync(ssl.key) : undefined,
|
|
75
|
+
cert: ssl.cert ? fs.readFileSync(ssl.cert) : undefined,
|
|
76
|
+
ca: ssl.ca ? fs.readFileSync(ssl.ca) : undefined
|
|
71
77
|
};
|
|
72
78
|
if (!options.key || !options.cert) {
|
|
73
79
|
throw new Error('HTTPS enabled but missing key or cert');
|
|
@@ -88,10 +94,11 @@ export default class SocketIOServer extends Module {
|
|
|
88
94
|
this.createSocketIOServer();
|
|
89
95
|
}
|
|
90
96
|
async stop() {
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
const { server, socketServer } = this;
|
|
98
|
+
if (socketServer)
|
|
99
|
+
await new Promise((resolve, reject) => socketServer.close(error => error ? reject(error) : resolve()));
|
|
93
100
|
if (this.#isSelfServer)
|
|
94
|
-
await new Promise((resolve, reject) =>
|
|
101
|
+
await new Promise((resolve, reject) => server?.close(error => error ? reject(error) : resolve()));
|
|
95
102
|
}
|
|
96
103
|
genSocketIOServerOptions() {
|
|
97
104
|
const options = {
|
|
@@ -127,7 +134,10 @@ export default class SocketIOServer extends Module {
|
|
|
127
134
|
return options;
|
|
128
135
|
}
|
|
129
136
|
createSocketIOServer() {
|
|
130
|
-
const
|
|
137
|
+
const { server } = this;
|
|
138
|
+
if (!server)
|
|
139
|
+
throw new Error('HTTP Server is not created');
|
|
140
|
+
const socketServer = this.socketServer = new Server(server, this.genSocketIOServerOptions());
|
|
131
141
|
socketServer.on('connection', async (socket) => {
|
|
132
142
|
try {
|
|
133
143
|
this.serverOnSocketConnection(socket);
|
|
@@ -145,22 +155,30 @@ export default class SocketIOServer extends Module {
|
|
|
145
155
|
const headers = socket.handshake.headers;
|
|
146
156
|
const callerId = String(headers['x-caller-id'] || '') || socket.id;
|
|
147
157
|
// client ip or caller service ip
|
|
148
|
-
const ip = String(headers['x-real-ip'] ||
|
|
158
|
+
const ip = String(headers['x-real-ip'] || socket.handshake.address);
|
|
149
159
|
// service name
|
|
150
160
|
const caller = String(headers['x-caller'] || 'anonymous');
|
|
161
|
+
const token = String(headers['x-token'] || '');
|
|
162
|
+
// check token
|
|
163
|
+
const { allow, reason } = oox.checkAllow(ip, caller, token);
|
|
164
|
+
if (!allow) {
|
|
165
|
+
socket.send(reason).disconnect(true);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
151
168
|
const connection = new oox.KeepAliveConnection(this.adapter, socket, {
|
|
152
|
-
|
|
169
|
+
ip,
|
|
153
170
|
name: caller,
|
|
154
171
|
id: callerId,
|
|
172
|
+
token,
|
|
155
173
|
});
|
|
156
174
|
oox.addKeepAliveConnection(connection);
|
|
157
175
|
this.bindServerConnectionEvents(connection);
|
|
158
176
|
this.adapter.bindCall(connection);
|
|
159
|
-
connection.enabled = true;
|
|
160
177
|
socket.emit(OOXEvent.READY, {
|
|
161
178
|
id: oox.config.id,
|
|
162
179
|
name: oox.config.name
|
|
163
180
|
});
|
|
181
|
+
connection.enabled = true;
|
|
164
182
|
}
|
|
165
183
|
/**
|
|
166
184
|
* 绑定服务器连接事件
|
|
@@ -168,7 +186,7 @@ export default class SocketIOServer extends Module {
|
|
|
168
186
|
*/
|
|
169
187
|
bindServerConnectionEvents(connection) {
|
|
170
188
|
const socket = connection.nativeConnection;
|
|
171
|
-
socket.on(OOXEvent.
|
|
189
|
+
socket.on(OOXEvent.REGISTRY_SYNC_CONNECTIONS, async (fn) => {
|
|
172
190
|
if ('function' !== typeof fn)
|
|
173
191
|
return;
|
|
174
192
|
oox.registry.onSyncConnections(connection, {}, fn);
|
|
@@ -3,7 +3,9 @@ export var OOXEvent;
|
|
|
3
3
|
OOXEvent["READY"] = "oox:ready";
|
|
4
4
|
OOXEvent["ENABLED"] = "oox:enabled";
|
|
5
5
|
OOXEvent["DISABLED"] = "oox:disabled";
|
|
6
|
-
OOXEvent["
|
|
6
|
+
OOXEvent["REGISTRY_SYNC_CONNECTIONS"] = "oox:registry:sync_connections";
|
|
7
|
+
OOXEvent["REGISTRY_SUBSCRIBE"] = "oox:registry:subscribe";
|
|
8
|
+
OOXEvent["REGISTRY_NOTIFY"] = "oox:registry:notify";
|
|
7
9
|
})(OOXEvent || (OOXEvent = {}));
|
|
8
10
|
export function isWebSocketURL(url) {
|
|
9
11
|
if ('string' === typeof url) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oox",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "OOX Service Engine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"http",
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
"framework",
|
|
11
11
|
"microservice",
|
|
12
12
|
"distributed",
|
|
13
|
-
"tracing"
|
|
13
|
+
"tracing",
|
|
14
|
+
"service-discovery",
|
|
15
|
+
"load-balancing"
|
|
14
16
|
],
|
|
15
17
|
"type": "module",
|
|
16
18
|
"main": "./index.js",
|
|
@@ -23,14 +25,16 @@
|
|
|
23
25
|
},
|
|
24
26
|
"./loader": "./bin/loader.mjs",
|
|
25
27
|
"./cli": "./bin/cli.js",
|
|
26
|
-
"./samples":
|
|
27
|
-
|
|
28
|
+
"./samples": {
|
|
29
|
+
"types": "./types/samples/index.d.ts",
|
|
30
|
+
"default": "./samples/index.js"
|
|
31
|
+
}
|
|
28
32
|
},
|
|
29
33
|
"bin": {
|
|
30
34
|
"oox": "./bin/cli.js"
|
|
31
35
|
},
|
|
32
36
|
"author": "lipingruan",
|
|
33
|
-
"homepage": "https://
|
|
37
|
+
"homepage": "https://gitee.com/lipingruan/oox",
|
|
34
38
|
"license": "MIT",
|
|
35
39
|
"dependencies": {
|
|
36
40
|
"chalk": "^5.6.2",
|