@abtnode/router-provider 1.6.21 → 1.6.24

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/lib/nginx/util.js CHANGED
@@ -8,13 +8,12 @@ const { NginxConfFile } = require('nginx-conf');
8
8
  const shelljs = require('shelljs');
9
9
  const findProcess = require('find-process');
10
10
  const moment = require('moment');
11
- const { MAX_UPLOAD_FILE_SIZE, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT } = require('@abtnode/constant');
12
- const checkDomainMatch = require('@abtnode/util/lib/check-domain-match');
13
- const { template404, template502, template5xx, templateWelcome } = require('@abtnode/router-templates');
14
- const logger = require('@abtnode/logger')(`${require('../../package.json').name}:provider:nginx:util`);
11
+ const { MAX_UPLOAD_FILE_SIZE } = require('@abtnode/constant');
12
+
13
+ const logger = require('@abtnode/logger')('router:nginx:util');
15
14
 
16
- const CLIENT_MAX_BODY_SIZE = process.env.MAX_UPLOAD_FILE_SIZE || MAX_UPLOAD_FILE_SIZE;
17
15
  const WORKER_CONNECTIONS = 1000 * 10; // 10K
16
+ const CLIENT_MAX_BODY_SIZE = process.env.MAX_UPLOAD_FILE_SIZE || MAX_UPLOAD_FILE_SIZE;
18
17
 
19
18
  const formatError = (errStr) => {
20
19
  if (!errStr) {
@@ -43,10 +42,10 @@ const formatError = (errStr) => {
43
42
  ).join(';');
44
43
  };
45
44
 
46
- const addTestServer = ({ configFilePath, port, upstreamPort }) =>
45
+ const addTestServer = ({ configPath, port, upstreamPort }) =>
47
46
  new Promise((resolve, reject) => {
48
47
  // eslint-disable-next-line consistent-return
49
- NginxConfFile.create(configFilePath, async (err, conf) => {
48
+ NginxConfFile.create(configPath, async (err, conf) => {
50
49
  if (err) {
51
50
  return reject(err);
52
51
  }
@@ -74,7 +73,7 @@ const addTestServer = ({ configFilePath, port, upstreamPort }) =>
74
73
  );
75
74
 
76
75
  conf.on('flushed', () => resolve());
77
- conf.live(configFilePath);
76
+ conf.live(configPath);
78
77
  conf.flush();
79
78
  });
80
79
  });
@@ -131,7 +130,7 @@ const getUserGroup = (username) => {
131
130
 
132
131
  const getMainTemplate = ({
133
132
  logDir,
134
- tmpDirectory,
133
+ tmpDir,
135
134
  nginxLoadModules = '',
136
135
  workerProcess,
137
136
  maxBodySize = CLIENT_MAX_BODY_SIZE,
@@ -152,11 +151,11 @@ http {
152
151
  default upgrade;
153
152
  '' close;
154
153
  }
155
- client_body_temp_path ${path.join(tmpDirectory, 'client_body')};
156
- proxy_temp_path ${path.join(tmpDirectory, 'proxy')};
157
- fastcgi_temp_path ${path.join(tmpDirectory, 'fastcgi')};
158
- uwsgi_temp_path ${path.join(tmpDirectory, 'uwsgi')};
159
- scgi_temp_path ${path.join(tmpDirectory, 'scgi')};
154
+ client_body_temp_path ${path.join(tmpDir, 'client_body')};
155
+ proxy_temp_path ${path.join(tmpDir, 'proxy')};
156
+ fastcgi_temp_path ${path.join(tmpDir, 'fastcgi')};
157
+ uwsgi_temp_path ${path.join(tmpDir, 'uwsgi')};
158
+ scgi_temp_path ${path.join(tmpDir, 'scgi')};
160
159
  client_max_body_size ${maxBodySize}m;
161
160
 
162
161
  log_format compression '$remote_addr - $remote_user [$time_local] '
@@ -174,7 +173,7 @@ http {
174
173
  const getNginxStatus = async (configPath) => {
175
174
  const list = await findProcess('name', /nginx:/);
176
175
  const result = {
177
- ownByABTNode: false,
176
+ managed: false,
178
177
  pid: 0,
179
178
  running: false,
180
179
  };
@@ -184,7 +183,7 @@ const getNginxStatus = async (configPath) => {
184
183
  result.running = true;
185
184
 
186
185
  if (abtnodeNginxProcess) {
187
- result.ownByABTNode = true;
186
+ result.managed = true;
188
187
  result.pid = abtnodeNginxProcess.pid;
189
188
  }
190
189
 
@@ -194,37 +193,6 @@ const getNginxStatus = async (configPath) => {
194
193
  return result;
195
194
  };
196
195
 
197
- const decideHttpPort = (port) => port || process.env.ABT_NODE_HTTP_PORT || DEFAULT_HTTP_PORT;
198
- const decideHttpsPort = (port) => port || process.env.ABT_NODE_HTTPS_PORT || DEFAULT_HTTPS_PORT;
199
-
200
- const findCertificate = (certs, domain) => {
201
- const results = certs
202
- .filter((cert) => [cert.domain, ...(cert.sans || [])].some((d) => checkDomainMatch(d, domain)))
203
- .sort((d1) => (d1.domain[0] === '*' ? 1 : -1)); // will first match a.b.com, then *.b.com
204
- return results[0];
205
- };
206
-
207
- /**
208
- * trim tail slash
209
- * @param {string} str
210
- * @returns {string}
211
- */
212
- const trimEndSlash = (str) => {
213
- if (str && str.length > 1 && str[str.length - 1] === '/') {
214
- return str.substr(0, str.length - 1);
215
- }
216
-
217
- return str;
218
- };
219
-
220
- const concatPath = (prefix = '', suffix = '') => {
221
- if (prefix === '/') {
222
- return suffix ? `~* .*${suffix}$` : '/';
223
- }
224
-
225
- return suffix ? `~* ^${prefix}.*${suffix}$` : prefix;
226
- };
227
-
228
196
  const compressFile = ({ sourceFile, targetFile, options = {} }) => {
229
197
  if (fs.existsSync(targetFile)) {
230
198
  fs.unlinkSync(targetFile);
@@ -297,16 +265,7 @@ module.exports = {
297
265
  formatError,
298
266
  getMissingModules,
299
267
  parseNginxConfigArgs,
300
- decideHttpPort,
301
- decideHttpsPort,
302
- concatPath,
303
- trimEndSlash,
304
- findCertificate,
305
268
  getNginxStatus,
306
269
  rotateNginxLogFile,
307
270
  getUserGroup,
308
- get404Template: (nodeInfo) => template404(nodeInfo),
309
- get502Template: (nodeInfo) => template502(nodeInfo),
310
- get5xxTemplate: (nodeInfo) => template5xx(nodeInfo),
311
- getWelcomeTemplate: (nodeInfo) => templateWelcome(nodeInfo),
312
271
  };
package/lib/util.js ADDED
@@ -0,0 +1,165 @@
1
+ const sortBy = require('lodash/sortBy');
2
+ const isValidDomain = require('is-valid-domain');
3
+ const checkDomainMatch = require('@abtnode/util/lib/check-domain-match');
4
+ const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
5
+ const { template404, template502, template5xx, templateWelcome } = require('@abtnode/router-templates');
6
+
7
+ const {
8
+ IP,
9
+ DEFAULT_HTTP_PORT,
10
+ DEFAULT_HTTPS_PORT,
11
+ DEFAULT_IP_DNS_DOMAIN_SUFFIX,
12
+ DOMAIN_FOR_DEFAULT_SITE,
13
+ ROUTING_RULE_TYPES,
14
+ SLOT_FOR_IP_DNS_SITE,
15
+ } = require('@abtnode/constant');
16
+
17
+ const decideHttpPort = (port) => port || process.env.ABT_NODE_HTTP_PORT || DEFAULT_HTTP_PORT;
18
+ const decideHttpsPort = (port) => port || process.env.ABT_NODE_HTTPS_PORT || DEFAULT_HTTPS_PORT;
19
+
20
+ const findCertificate = (certs, domain) => {
21
+ const results = certs
22
+ .filter((cert) => [cert.domain, ...(cert.sans || [])].some((d) => checkDomainMatch(d, domain)))
23
+ .sort((d1) => (d1.domain[0] === '*' ? 1 : -1)); // will first match a.b.com, then *.b.com
24
+ return results[0];
25
+ };
26
+
27
+ const trimEndSlash = (str) => {
28
+ if (str && str.length > 1 && str[str.length - 1] === '/') {
29
+ return str.substr(0, str.length - 1);
30
+ }
31
+
32
+ return str;
33
+ };
34
+
35
+ const concatPath = (prefix = '', suffix = '') => {
36
+ if (prefix === '/') {
37
+ return suffix ? `~* .*${suffix}$` : '/';
38
+ }
39
+
40
+ return suffix ? `~* ^${prefix}.*${suffix}$` : prefix;
41
+ };
42
+
43
+ const formatRoutingTable = (routingTable, onRule) => {
44
+ const sites = {};
45
+ const configs = [];
46
+
47
+ routingTable.forEach((site) => {
48
+ let { domain } = site;
49
+ if (site.domain === DOMAIN_FOR_DEFAULT_SITE) {
50
+ domain = '_';
51
+ }
52
+
53
+ configs.push({ domain, corsAllowedOrigins: site.corsAllowedOrigins });
54
+
55
+ if (!sites[domain]) {
56
+ sites[domain] = {
57
+ domain,
58
+ rules: [],
59
+ port: site.port,
60
+ corsAllowedOrigins: site.corsAllowedOrigins,
61
+ };
62
+ }
63
+
64
+ (site.rules || []).forEach((x) => {
65
+ const prefix = trimEndSlash(x.from.pathPrefix || '/');
66
+ const groupPrefix = trimEndSlash(x.from.groupPathPrefix || '/');
67
+ const suffix = trimEndSlash(x.from.pathSuffix || '');
68
+
69
+ const rule = {
70
+ ruleId: x.id,
71
+ type: x.to.type,
72
+ prefix,
73
+ groupPrefix,
74
+ suffix,
75
+ response: x.to.response,
76
+ };
77
+ if (x.to.type === ROUTING_RULE_TYPES.REDIRECT) {
78
+ rule.redirectCode = x.to.redirectCode || 302;
79
+ rule.url = x.to.url;
80
+ } else {
81
+ rule.port = +x.to.port;
82
+ rule.did = x.to.did;
83
+ rule.realDid = x.to.realDid;
84
+ rule.target = trimEndSlash(normalizePathPrefix(x.to.target || '/'));
85
+ rule.services = x.services || [];
86
+ }
87
+
88
+ const tmpPath = concatPath(prefix, suffix);
89
+ const tmpRules = sites[domain].rules;
90
+ if (!tmpRules.find(({ prefix: p, suffix: s }) => concatPath(p, s) === tmpPath)) {
91
+ sites[domain].rules.push(rule);
92
+ if (typeof onRule === 'function') {
93
+ onRule(sites[domain].rules, rule);
94
+ }
95
+ }
96
+ });
97
+
98
+ const { rules } = sites[domain];
99
+ const rulesWithoutSuffix = sortBy(rules.filter((x) => !x.suffix), (x) => -x.prefix.length); // prettier-ignore
100
+ const rulesWithSuffix = sortBy(rules.filter((x) => x.suffix), (x) => -x.prefix.length); // prettier-ignore
101
+
102
+ sites[domain].rules = rulesWithoutSuffix.concat(rulesWithSuffix);
103
+ });
104
+
105
+ return { sites: Object.values(sites), configs };
106
+ };
107
+
108
+ const isSpecificDomain = (domain) => {
109
+ if (isValidDomain(domain) === false) {
110
+ return false;
111
+ }
112
+
113
+ if (domain.endsWith(DEFAULT_IP_DNS_DOMAIN_SUFFIX)) {
114
+ return false;
115
+ }
116
+
117
+ return true;
118
+ };
119
+
120
+ const toSlotDomain = (domain) => {
121
+ if (domain.endsWith(DEFAULT_IP_DNS_DOMAIN_SUFFIX)) {
122
+ const subDomain = domain.split('.').shift();
123
+ const matches = subDomain.match(IP);
124
+ if (matches) {
125
+ return domain.replace(matches[0].slice(1), SLOT_FOR_IP_DNS_SITE);
126
+ }
127
+ }
128
+
129
+ return domain;
130
+ };
131
+
132
+ const findRule = (rules, url) =>
133
+ rules.find((x) => {
134
+ const { prefix, suffix = '' } = x;
135
+ if (suffix) {
136
+ return url.startsWith(prefix) && url.endsWith(suffix);
137
+ }
138
+
139
+ if (prefix === '/' && prefix === url) {
140
+ return true;
141
+ }
142
+
143
+ return url.startsWith(prefix);
144
+ });
145
+ const matchRule = (rules, url) => {
146
+ const rulesWithSuffix = rules.filter((x) => x.suffix);
147
+ const rulesWithoutSuffix = rules.filter((x) => !x.suffix);
148
+ return findRule(rulesWithSuffix, url) || findRule(rulesWithoutSuffix, url);
149
+ };
150
+
151
+ module.exports = {
152
+ decideHttpPort,
153
+ decideHttpsPort,
154
+ findCertificate,
155
+ concatPath,
156
+ trimEndSlash,
157
+ formatRoutingTable,
158
+ isSpecificDomain,
159
+ toSlotDomain,
160
+ matchRule,
161
+ get404Template: (info) => template404(info),
162
+ get502Template: (info) => template502(info),
163
+ get5xxTemplate: (info) => template5xx(info),
164
+ getWelcomeTemplate: (info) => templateWelcome(info),
165
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abtnode/router-provider",
3
- "version": "1.6.21",
3
+ "version": "1.6.24",
4
4
  "description": "Routing engine implementations for abt node",
5
5
  "author": "polunzh <polunzh@gmail.com>",
6
6
  "homepage": "https://github.com/ArcBlock/blocklet-server#readme",
@@ -32,25 +32,34 @@
32
32
  "url": "https://github.com/ArcBlock/blocklet-server/issues"
33
33
  },
34
34
  "dependencies": {
35
- "@abtnode/constant": "1.6.21",
36
- "@abtnode/logger": "1.6.21",
37
- "@abtnode/router-templates": "1.6.21",
38
- "@abtnode/util": "1.6.21",
35
+ "@abtnode/constant": "1.6.24",
36
+ "@abtnode/logger": "1.6.24",
37
+ "@abtnode/router-templates": "1.6.24",
38
+ "@abtnode/util": "1.6.24",
39
39
  "axios": "^0.25.0",
40
40
  "debug": "^4.3.3",
41
41
  "find-process": "^1.4.3",
42
42
  "fkill": "^7.0.1",
43
43
  "fs-extra": "^10.0.0",
44
44
  "get-port": "^5.1.1",
45
+ "http-proxy": "^1.18.1",
46
+ "is-valid-domain": "^0.1.6",
45
47
  "lodash": "^4.17.21",
48
+ "lru-cache": "^7.4.0",
46
49
  "moment": "^2.29.1",
47
50
  "nginx-conf": "^1.5.0",
51
+ "object-hash": "^3.0.0",
48
52
  "promise-retry": "^2.0.1",
49
53
  "shelljs": "^0.8.4",
50
- "tar": "^6.1.0"
54
+ "tar": "^6.1.0",
55
+ "url-join": "^4.0.1",
56
+ "uuid": "^8.3.2",
57
+ "valid-url": "^1.0.9"
51
58
  },
52
59
  "devDependencies": {
53
- "fs-extra": "^10.0.0"
60
+ "bluebird": "^3.7.2",
61
+ "fs-extra": "^10.0.0",
62
+ "needle": "^3.0.0"
54
63
  },
55
- "gitHead": "864ae21711c119948475057a1f634fd7d16ae91a"
64
+ "gitHead": "6bd8792a155ebbbefea6ca3d42c5b59b354d9879"
56
65
  }
package/lib/none/index.js DELETED
@@ -1,50 +0,0 @@
1
- /* eslint-disable no-empty-function */
2
- const BaseProvider = require('../base');
3
-
4
- class NoneProvider extends BaseProvider {
5
- constructor() {
6
- super('none');
7
- }
8
-
9
- async update() {}
10
-
11
- async reload() {}
12
-
13
- async start() {}
14
-
15
- async restart() {}
16
-
17
- async stop() {}
18
-
19
- initialize() {}
20
-
21
- async validateConfig() {}
22
-
23
- async rotateLogs() {}
24
- }
25
-
26
- NoneProvider.describe = () => {
27
- const result = NoneProvider.check();
28
- return {
29
- name: 'none',
30
- description: 'This provider does nothing, you must access blocklets through IP + Port',
31
- error: result.error,
32
- available: result.available,
33
- running: result.running,
34
- };
35
- };
36
-
37
- NoneProvider.check = () => ({
38
- available: true,
39
- running: true,
40
- error: '',
41
- });
42
-
43
- NoneProvider.getStatus = () => ({
44
- pid: 0,
45
- running: false,
46
- });
47
-
48
- NoneProvider.exists = () => true;
49
-
50
- module.exports = NoneProvider;