@abtnode/blocklet-services 1.6.26 → 1.6.29
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 +1 -5
- package/{lib → api}/cache.js +0 -0
- package/api/index.js +296 -0
- package/{services/auth → api}/libs/auth.js +24 -8
- package/api/libs/env.js +7 -0
- package/{services/auth → api}/libs/jwt.js +1 -0
- package/api/middlewares/check-admin-permission.js +15 -0
- package/api/middlewares/check-running.js +46 -0
- package/api/routes/blocklet.js +98 -0
- package/api/routes/env.js +27 -0
- package/{services/auth/routes → api/services/auth/connect}/invite.js +5 -4
- package/{services/auth/routes → api/services/auth/connect}/issue-passport.js +6 -2
- package/{services/auth/routes → api/services/auth/connect}/login.js +18 -10
- package/api/services/auth/connect/lost-passport-issue.js +10 -0
- package/{services/auth/routes → api/services/auth/connect}/lost-passport-list.js +1 -1
- package/api/services/auth/index.js +189 -0
- package/api/services/auth/passport.js +22 -0
- package/api/services/auth/session.js +31 -0
- package/{services/auth/routes/notification.js → api/services/notification/index.js} +25 -9
- package/api/services/static.js +76 -0
- package/{services/auth → api}/state/index.js +0 -0
- package/{services/auth → api}/state/message.js +0 -0
- package/api/util/attach-shared-utils.js +149 -0
- package/api/util/constants.js +10 -0
- package/api/util/format-context.js +24 -0
- package/{services/auth → api}/util/index.js +31 -1
- package/build/asset-manifest.json +32 -30
- package/build/index.html +1 -1
- package/build/precache-manifest.f8d516b676d205d1f6e2c4e869fbf297.js +154 -0
- package/build/service-worker.js +2 -2
- package/build/static/css/2.d49e994f.chunk.css +2 -0
- package/build/static/css/{2.cc9dc85c.chunk.css.map → 2.d49e994f.chunk.css.map} +1 -1
- package/build/static/js/2.ca22e0d7.chunk.js +3 -0
- package/build/static/js/{2.90523f87.chunk.js.LICENSE.txt → 2.ca22e0d7.chunk.js.LICENSE.txt} +0 -0
- package/build/static/js/2.ca22e0d7.chunk.js.map +1 -0
- package/build/static/js/3.38949d38.chunk.js +3 -0
- package/build/static/js/{3.e6540184.chunk.js.LICENSE.txt → 3.38949d38.chunk.js.LICENSE.txt} +0 -0
- package/build/static/js/3.38949d38.chunk.js.map +1 -0
- package/build/static/js/4.97f8d423.chunk.js +2 -0
- package/build/static/js/4.97f8d423.chunk.js.map +1 -0
- package/build/static/js/5.8149df59.chunk.js +2 -0
- package/build/static/js/5.8149df59.chunk.js.map +1 -0
- package/build/static/js/6.001b8434.chunk.js +2 -0
- package/build/static/js/6.001b8434.chunk.js.map +1 -0
- package/build/static/js/7.f30a5254.chunk.js +2 -0
- package/build/static/js/7.f30a5254.chunk.js.map +1 -0
- package/build/static/js/8.e354cbf1.chunk.js +2 -0
- package/build/static/js/8.e354cbf1.chunk.js.map +1 -0
- package/build/static/js/main.561b39e2.chunk.js +2 -0
- package/build/static/js/main.561b39e2.chunk.js.map +1 -0
- package/build/static/js/runtime-main.8ddd5828.js +2 -0
- package/build/static/js/runtime-main.8ddd5828.js.map +1 -0
- package/{services/auth/meta.json → configs/auth.json} +2 -2
- package/package.json +27 -24
- package/build/precache-manifest.f3419eb785f255da7655fa425fc775a1.js +0 -150
- package/build/static/css/2.cc9dc85c.chunk.css +0 -2
- package/build/static/js/2.90523f87.chunk.js +0 -3
- package/build/static/js/2.90523f87.chunk.js.map +0 -1
- package/build/static/js/3.e6540184.chunk.js +0 -3
- package/build/static/js/3.e6540184.chunk.js.map +0 -1
- package/build/static/js/4.4410aa8a.chunk.js +0 -2
- package/build/static/js/4.4410aa8a.chunk.js.map +0 -1
- package/build/static/js/5.967448ae.chunk.js +0 -2
- package/build/static/js/5.967448ae.chunk.js.map +0 -1
- package/build/static/js/6.1de827ed.chunk.js +0 -2
- package/build/static/js/6.1de827ed.chunk.js.map +0 -1
- package/build/static/js/7.cb386b54.chunk.js +0 -2
- package/build/static/js/7.cb386b54.chunk.js.map +0 -1
- package/build/static/js/main.c51a8d5b.chunk.js +0 -2
- package/build/static/js/main.c51a8d5b.chunk.js.map +0 -1
- package/build/static/js/runtime-main.24dfe4a3.js +0 -2
- package/build/static/js/runtime-main.24dfe4a3.js.map +0 -1
- package/lib/index.js +0 -443
- package/lib/mount.js +0 -52
- package/lib/util.js +0 -17
- package/services/auth/index.js +0 -290
- package/services/auth/routes/blocklet-info.js +0 -33
- package/services/auth/routes/env.js +0 -33
- package/services/auth/routes/lost-passport-issue.js +0 -5
- package/services/auth/routes/passport.js +0 -18
- package/services/auth/routes/session.js +0 -27
package/lib/index.js
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const http = require('http');
|
|
3
|
-
const get = require('lodash/get');
|
|
4
|
-
const morgan = require('morgan');
|
|
5
|
-
const express = require('express');
|
|
6
|
-
require('express-async-errors');
|
|
7
|
-
const cors = require('cors');
|
|
8
|
-
const compression = require('compression');
|
|
9
|
-
const cookieParser = require('cookie-parser');
|
|
10
|
-
const bodyParser = require('body-parser');
|
|
11
|
-
const RotatingFileStream = require('rotating-file-stream');
|
|
12
|
-
const httpProxy = require('http-proxy');
|
|
13
|
-
const serveStatic = require('serve-static');
|
|
14
|
-
const moment = require('dayjs');
|
|
15
|
-
const minimatch = require('minimatch');
|
|
16
|
-
const { NODE_SERVICES } = require('@abtnode/constant');
|
|
17
|
-
const { BlockletEvents } = require('@blocklet/meta/lib/constants');
|
|
18
|
-
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
19
|
-
const eventHub =
|
|
20
|
-
process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
|
|
21
|
-
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
22
|
-
|
|
23
|
-
const logger = require('@abtnode/logger')(require('../package.json').name);
|
|
24
|
-
|
|
25
|
-
const authModule = require('../services/auth');
|
|
26
|
-
|
|
27
|
-
const mount = require('./mount');
|
|
28
|
-
const cache = require('./cache');
|
|
29
|
-
const { ensureProxyUrl } = require('./util');
|
|
30
|
-
|
|
31
|
-
const logFileGenerator = (time, index) => {
|
|
32
|
-
if (!time) {
|
|
33
|
-
return 'service.log';
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let filename = `service-${moment(time).subtract(1, 'day').format('YYYY-MM-DD')}`; // prev date
|
|
37
|
-
|
|
38
|
-
if (index > 1) {
|
|
39
|
-
filename = `${filename}-${index}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return `${filename}.log.gz`;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const isProduction = process.env.NODE_ENV === 'production' || process.env.ABT_NODE_SERVICE_ENV === 'production';
|
|
46
|
-
const isE2E = process.env.NODE_ENV === 'e2e';
|
|
47
|
-
|
|
48
|
-
// Format context: https://github.com/graphql/express-graphql
|
|
49
|
-
const formatContext = (ctx = {}) => {
|
|
50
|
-
if (ctx && ctx.user) {
|
|
51
|
-
delete ctx.user.avatar;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const port = isProduction ? get(ctx, 'headers[x-real-port]', '') : '';
|
|
55
|
-
const hostname = get(ctx, 'headers[x-real-hostname]', ctx.hostname);
|
|
56
|
-
const protocol = get(ctx, 'headers[x-real-protocol]', 'http').replace(/:$/, '');
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
protocol,
|
|
60
|
-
user: ctx.user || null,
|
|
61
|
-
url: ctx.originalUrl,
|
|
62
|
-
query: ctx.query,
|
|
63
|
-
hostname,
|
|
64
|
-
port: Number(port) === 80 ? '' : Number(port),
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// eslint-disable-next-line no-shadow
|
|
69
|
-
const attachSharedUtils = (node, req, options) => {
|
|
70
|
-
req.getBlockletUrl = () => req.headers['x-blocklet-url'] || get(options, 'blockletUrl', '');
|
|
71
|
-
req.getBlockletDid = () => req.headers['x-blocklet-did'] || get(options, 'blockletDid', '');
|
|
72
|
-
req.getBlockletRealDid = () => req.headers['x-blocklet-real-did'] || get(options, 'blockletRealDid', '');
|
|
73
|
-
req.getRoutingRuleId = () => req.headers['x-routing-rule-id'] || get(options, 'routingRuleId', '');
|
|
74
|
-
|
|
75
|
-
req.getServiceContext = () => formatContext(req);
|
|
76
|
-
|
|
77
|
-
req.getRoutingRule = async () => {
|
|
78
|
-
const ruleId = req.getRoutingRuleId(req);
|
|
79
|
-
if (!ruleId) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
let rule = cache.get(ruleId);
|
|
84
|
-
|
|
85
|
-
if (!rule) {
|
|
86
|
-
rule = await node.getRoutingRuleById(ruleId);
|
|
87
|
-
cache.set(ruleId, rule);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return rule;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @return obj | null
|
|
95
|
-
*/
|
|
96
|
-
req.getServiceConfig = async (serviceName) => {
|
|
97
|
-
const ruleId = req.getRoutingRuleId(req);
|
|
98
|
-
const name = serviceName || get(req, 'service.current', '');
|
|
99
|
-
if (!ruleId || !name) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const cacheKeys = {
|
|
104
|
-
rule: cache.keyFns.routingRule(ruleId),
|
|
105
|
-
config: cache.keyFns.serviceConfig(ruleId, name),
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// Return cached config if exists
|
|
109
|
-
const cached = cache.get(cacheKeys.config);
|
|
110
|
-
if (cached) {
|
|
111
|
-
return cached;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Find rule
|
|
115
|
-
let rule = cache.get(cacheKeys.rule);
|
|
116
|
-
if (!rule) {
|
|
117
|
-
rule = await node.getRoutingRuleById(ruleId);
|
|
118
|
-
cache.set(cacheKeys.rule, rule);
|
|
119
|
-
}
|
|
120
|
-
if (!rule) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// if is auth service, get config from blocklet meta
|
|
125
|
-
if (name === NODE_SERVICES.AUTH_SERVICE) {
|
|
126
|
-
// find blocklet
|
|
127
|
-
let blocklet = await req.getBlocklet();
|
|
128
|
-
if (!blocklet) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const realDid = req.getBlockletRealDid();
|
|
133
|
-
if (realDid && blocklet.meta.did !== realDid) {
|
|
134
|
-
blocklet = (blocklet.children || []).find((x) => x.meta.did === realDid);
|
|
135
|
-
}
|
|
136
|
-
if (!blocklet) {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// find interface
|
|
141
|
-
let interfaceName = rule.to.realInterfaceName;
|
|
142
|
-
|
|
143
|
-
// we should only use rule.to.realInterfaceName, rule.to.interfaceName is for backward compatible
|
|
144
|
-
if (!interfaceName) {
|
|
145
|
-
logger.error(
|
|
146
|
-
`rule.to.realInterfaceName was not fround, please reInstall blocklet ${rule.to.did} to eliminate hidden bugs`
|
|
147
|
-
);
|
|
148
|
-
interfaceName = rule.to.interfaceName;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const _interface = blocklet.meta.interfaces.find((x) => x.name === interfaceName);
|
|
152
|
-
if (!_interface) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// find service
|
|
157
|
-
const service = (_interface.services || []).find((x) => x.name === NODE_SERVICES.AUTH_SERVICE);
|
|
158
|
-
if (!service) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return service.config;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Parse config from rule
|
|
166
|
-
const services = rule.services || [];
|
|
167
|
-
const service = services.find((x) => x.name === name);
|
|
168
|
-
if (service) {
|
|
169
|
-
let config = {};
|
|
170
|
-
try {
|
|
171
|
-
logger.info('service config deserialize', service);
|
|
172
|
-
config = JSON.parse(service.config || '{}');
|
|
173
|
-
cache.set(cacheKeys.config, config);
|
|
174
|
-
} catch (err) {
|
|
175
|
-
logger.error('service config deserialize error', { error: err });
|
|
176
|
-
}
|
|
177
|
-
return config;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return null;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
req.getBlocklet = async () => {
|
|
184
|
-
const did = req.getBlockletDid();
|
|
185
|
-
if (!did) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const cacheKey = cache.keyFns.blocklet(did);
|
|
190
|
-
let blocklet = cache.get(cacheKey);
|
|
191
|
-
if (!blocklet) {
|
|
192
|
-
const context = req.getServiceContext();
|
|
193
|
-
blocklet = await node.getBlocklet({ did, attachRuntimeInfo: false }, context);
|
|
194
|
-
if (blocklet) {
|
|
195
|
-
cache.set(cacheKey, blocklet);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return blocklet;
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
req.getNodeInfo = async () => {
|
|
203
|
-
const cacheKey = cache.keyFns.node();
|
|
204
|
-
let nodeInfo = cache.get(cacheKey);
|
|
205
|
-
if (!nodeInfo) {
|
|
206
|
-
nodeInfo = await node.states.node.read();
|
|
207
|
-
cache.set(cacheKey, nodeInfo);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return nodeInfo;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
req.getBlockletInfo = async () => {
|
|
214
|
-
const [blocklet, info] = await Promise.all([req.getBlocklet(), req.getNodeInfo()]);
|
|
215
|
-
if (!blocklet) {
|
|
216
|
-
throw new Error('Blocklet does not exist');
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return getBlockletInfo(blocklet, info.sk);
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
req.cache = cache;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const distDir = path.resolve(__dirname, '../build');
|
|
226
|
-
|
|
227
|
-
module.exports = function createServer(node, serverOptions = {}, serviceModules = []) {
|
|
228
|
-
const server = express();
|
|
229
|
-
const proxy = httpProxy.createProxyServer({});
|
|
230
|
-
|
|
231
|
-
// simple router, let each service handle the websocket connection
|
|
232
|
-
const wsRoutingRules = [
|
|
233
|
-
// final route: directly proxy all websocket request to target blocklet
|
|
234
|
-
{
|
|
235
|
-
path: '**',
|
|
236
|
-
handle: async (req, socket, head) => {
|
|
237
|
-
const { target } = ensureProxyUrl(req);
|
|
238
|
-
if (target) {
|
|
239
|
-
proxy.ws(req, socket, head, { target }, (error) => {
|
|
240
|
-
if (error) {
|
|
241
|
-
logger.error('socket proxy error', { error });
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
} else {
|
|
245
|
-
logger.error('socket proxy error: cannot find target service');
|
|
246
|
-
socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
|
|
247
|
-
socket.destroy();
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
},
|
|
251
|
-
];
|
|
252
|
-
const wsRouter = {
|
|
253
|
-
// eslint-disable-next-line no-shadow
|
|
254
|
-
use(path, handler) {
|
|
255
|
-
const finalRoute = wsRoutingRules.pop();
|
|
256
|
-
wsRoutingRules.push({ path, handle: handler });
|
|
257
|
-
wsRoutingRules.push(finalRoute);
|
|
258
|
-
},
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
// eslint-disable-next-line no-unused-vars
|
|
262
|
-
proxy.on('proxyReq', (proxyReq, req, res, options) => {
|
|
263
|
-
if (req.rawBody) {
|
|
264
|
-
// Since we already consumed request stream, we need to write req.rawBody to proxy request here
|
|
265
|
-
proxyReq.write(req.rawBody);
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// Bust cache on events from daemon
|
|
270
|
-
[BlockletEvents.updated, BlockletEvents.started, BlockletEvents.removed, BlockletEvents.statusChange].forEach(
|
|
271
|
-
(name) => {
|
|
272
|
-
eventHub.on(name, (data) => {
|
|
273
|
-
const did = get(data, 'meta.did');
|
|
274
|
-
if (did) {
|
|
275
|
-
logger.info('delete blocklet cache on update', { did, pid: process.pid });
|
|
276
|
-
cache.del(cache.keyFns.blocklet(did));
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
);
|
|
281
|
-
eventHub.on('node.updated', () => {
|
|
282
|
-
logger.info('node update', { pid: process.pid });
|
|
283
|
-
cache.del(cache.keyFns.node());
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
logger.info('init params', { isProduction, serverOptions });
|
|
287
|
-
|
|
288
|
-
server.set('trust proxy', 'loopback');
|
|
289
|
-
server.disable('x-powered-by');
|
|
290
|
-
|
|
291
|
-
server.use(compression());
|
|
292
|
-
server.use(cookieParser());
|
|
293
|
-
|
|
294
|
-
server.use(
|
|
295
|
-
bodyParser.json({
|
|
296
|
-
// We have to set a larger hard limit since
|
|
297
|
-
limit: '2mb',
|
|
298
|
-
|
|
299
|
-
// https://flaviocopes.com/express-get-raw-body/
|
|
300
|
-
// Side effects: this will double the memory consumption
|
|
301
|
-
verify: (req, res, buf) => {
|
|
302
|
-
req.rawBody = buf;
|
|
303
|
-
},
|
|
304
|
-
})
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
// NOTE: will be overwrite by Blocklet Server in production
|
|
308
|
-
server.use(cors());
|
|
309
|
-
|
|
310
|
-
// Shared util functions on current request
|
|
311
|
-
server.use((req, res, next) => {
|
|
312
|
-
attachSharedUtils(node, req, serverOptions);
|
|
313
|
-
next();
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
/* istanbul ignore if */
|
|
317
|
-
if (isProduction) {
|
|
318
|
-
const accessLogStream = RotatingFileStream.createStream(logFileGenerator, {
|
|
319
|
-
interval: '1d',
|
|
320
|
-
path: process.env.ABT_NODE_LOG_DIR,
|
|
321
|
-
compress: 'gzip',
|
|
322
|
-
});
|
|
323
|
-
server.use(morgan('combined', { stream: accessLogStream }));
|
|
324
|
-
/* istanbul ignore else */
|
|
325
|
-
} else {
|
|
326
|
-
server.use(
|
|
327
|
-
morgan((tokens, req, res) => {
|
|
328
|
-
const log = [
|
|
329
|
-
tokens.method(req, res),
|
|
330
|
-
tokens.url(req, res),
|
|
331
|
-
tokens.status(req, res),
|
|
332
|
-
tokens.res(req, res, 'content-length'),
|
|
333
|
-
'-',
|
|
334
|
-
tokens['response-time'](req, res),
|
|
335
|
-
'ms',
|
|
336
|
-
].join(' ');
|
|
337
|
-
|
|
338
|
-
return log;
|
|
339
|
-
})
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Serve static assets from the service
|
|
344
|
-
if (isProduction || isE2E) {
|
|
345
|
-
server.use('/.service/@abtnode/auth-service', serveStatic(distDir, { index: false }));
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Mount services
|
|
349
|
-
// Each service can mount any number of middleware function or api function
|
|
350
|
-
|
|
351
|
-
// mount Auth Service
|
|
352
|
-
if (process.env.NODE_ENV !== 'test') {
|
|
353
|
-
mount({
|
|
354
|
-
node,
|
|
355
|
-
server,
|
|
356
|
-
wsRouter,
|
|
357
|
-
service: {
|
|
358
|
-
options: Object.assign({}, serverOptions, {
|
|
359
|
-
sessionSecret: process.env.ABT_NODE_SESSION_SECRET,
|
|
360
|
-
sessionTtl: process.env.ABT_NODE_SESSION_TTL,
|
|
361
|
-
}),
|
|
362
|
-
name: NODE_SERVICES.AUTH_SERVICE,
|
|
363
|
-
module: authModule,
|
|
364
|
-
},
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
serviceModules.forEach((serviceModule) => {
|
|
368
|
-
mount({
|
|
369
|
-
node,
|
|
370
|
-
server,
|
|
371
|
-
wsRouter,
|
|
372
|
-
service: serviceModule,
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
// After all service middleware, we can now safely pass all traffic to blocklets
|
|
377
|
-
server.use((req, res, next) => {
|
|
378
|
-
const { target } = ensureProxyUrl(req);
|
|
379
|
-
|
|
380
|
-
if (target) {
|
|
381
|
-
proxy.web(
|
|
382
|
-
req,
|
|
383
|
-
res,
|
|
384
|
-
{
|
|
385
|
-
target,
|
|
386
|
-
},
|
|
387
|
-
(error) => {
|
|
388
|
-
if (error) {
|
|
389
|
-
console.error(error);
|
|
390
|
-
logger.error('http proxy error', { error });
|
|
391
|
-
res.status(502).send(`Can not proxy to upstream blocklet: ${target}`);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
);
|
|
395
|
-
} else {
|
|
396
|
-
next();
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
// Following handlers exist just in case
|
|
401
|
-
|
|
402
|
-
// 404 handler
|
|
403
|
-
server.use((req, res) => {
|
|
404
|
-
res.status(404).send('Blocklet Service: You should not be here!');
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
// error handler
|
|
408
|
-
// eslint-disable-next-line no-unused-vars
|
|
409
|
-
server.use((err, req, res, next) => {
|
|
410
|
-
console.error('service error', { error: err });
|
|
411
|
-
res.status(500).send('Blocklet Service: Something broke!');
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
// handle websocket connect request like http
|
|
415
|
-
const httpServer = http.createServer(server);
|
|
416
|
-
|
|
417
|
-
httpServer.on('upgrade', async (req, socket, head) => {
|
|
418
|
-
attachSharedUtils(node, req, serverOptions);
|
|
419
|
-
|
|
420
|
-
// find matched handler registered by each service
|
|
421
|
-
const { pathname } = new URL(req.url, `http://${req.headers.host || 'unknown'}`);
|
|
422
|
-
const routes = wsRoutingRules.filter((x) => minimatch(normalizePathPrefix(pathname), normalizePathPrefix(x.path)));
|
|
423
|
-
|
|
424
|
-
let routeIndex = 0;
|
|
425
|
-
const next = () => {
|
|
426
|
-
const route = routes[routeIndex];
|
|
427
|
-
if (route) {
|
|
428
|
-
routeIndex++;
|
|
429
|
-
route.handle(req, socket, head, next);
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
next();
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
server.listen = httpServer.listen.bind(httpServer);
|
|
437
|
-
|
|
438
|
-
return server;
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
module.exports.formatContext = formatContext;
|
|
442
|
-
module.exports.logFileGenerator = logFileGenerator;
|
|
443
|
-
module.exports.attachSharedUtils = attachSharedUtils;
|
package/lib/mount.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/* eslint-disable global-require */
|
|
2
|
-
/* eslint-disable import/no-dynamic-require */
|
|
3
|
-
const fs = require('fs-extra');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const express = require('express');
|
|
6
|
-
const set = require('lodash/set');
|
|
7
|
-
|
|
8
|
-
const logger = require('@abtnode/logger')(require('../package.json').name);
|
|
9
|
-
|
|
10
|
-
module.exports = function mount({ node, server, wsRouter, service }) {
|
|
11
|
-
try {
|
|
12
|
-
const serviceModule = service.module;
|
|
13
|
-
|
|
14
|
-
const dataDir = path.join(node.dataDirs.services, service.name);
|
|
15
|
-
if (!fs.pathExistsSync(dataDir)) {
|
|
16
|
-
fs.mkdirpSync(dataDir);
|
|
17
|
-
}
|
|
18
|
-
const serviceOptions = { dataDir, ...service.options };
|
|
19
|
-
|
|
20
|
-
let serviceObject = serviceModule;
|
|
21
|
-
if (typeof serviceModule === 'function') {
|
|
22
|
-
serviceObject = serviceModule(node, server, serviceOptions);
|
|
23
|
-
}
|
|
24
|
-
const { init, name, version } = serviceObject;
|
|
25
|
-
|
|
26
|
-
// Create new router for each service
|
|
27
|
-
const router = express.Router();
|
|
28
|
-
|
|
29
|
-
// Set current service before current service runs
|
|
30
|
-
router.use((req, res, next) => {
|
|
31
|
-
set(req, 'service.current', name);
|
|
32
|
-
next();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Mount service middleware
|
|
36
|
-
init({ node, httpRouter: server, serviceHttpRouter: router, wsRouter, options: serviceOptions });
|
|
37
|
-
|
|
38
|
-
// Unset current service when all middleware is done
|
|
39
|
-
router.use((req, res, next) => {
|
|
40
|
-
set(req, 'service.current', '');
|
|
41
|
-
next();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Attach the service router to main application
|
|
45
|
-
server.use(router);
|
|
46
|
-
|
|
47
|
-
logger.info(`service ${name}@${version} mounted successfully`, { name, version });
|
|
48
|
-
} catch (err) {
|
|
49
|
-
logger.error(`service ${service.name} failed to mount due to ${err.message}`);
|
|
50
|
-
throw err;
|
|
51
|
-
}
|
|
52
|
-
};
|
package/lib/util.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const ensureProxyUrl = (req) => {
|
|
2
|
-
const target = req.headers['x-blocklet-url'];
|
|
3
|
-
|
|
4
|
-
if (target) {
|
|
5
|
-
const pathPrefix = req.headers['x-routing-rule-path-prefix'];
|
|
6
|
-
|
|
7
|
-
if (pathPrefix && pathPrefix !== '/') {
|
|
8
|
-
req.url = `${pathPrefix}${req.url}`;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return { target };
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
module.exports = {
|
|
16
|
-
ensureProxyUrl,
|
|
17
|
-
};
|