@abtnode/router-provider 1.16.14-beta-3127f514 → 1.16.14-beta-c2843ec5

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.
@@ -0,0 +1,20 @@
1
+ map $arg_w $image_width {
2
+ default 1200;
3
+ ~^(\d+)$ $1;
4
+ }
5
+ map $arg_h $image_height {
6
+ default -;
7
+ ~^(\d+)$ $1;
8
+ }
9
+ map $arg_r $image_rotate {
10
+ default 0;
11
+ ~^(\d+)$ $1;
12
+ }
13
+ map $arg_q $image_quality {
14
+ default 90;
15
+ ~^(\d+)$ $1;
16
+ }
17
+ map $arg_s $image_sharpen {
18
+ default 0;
19
+ ~^(\d+)$ $1;
20
+ }
@@ -0,0 +1,13 @@
1
+ image_filter_buffer 16M;
2
+ image_filter rotate $image_rotate;
3
+ image_filter crop $image_width $image_height;
4
+ # FIXME: @wangshijun turn on this will improve jpeg and breaks png
5
+ image_filter_interlace on;
6
+ image_filter_transparency on;
7
+ image_filter_jpeg_quality $image_quality;
8
+ image_filter_webp_quality $image_quality;
9
+ image_filter_sharpen $image_sharpen;
10
+
11
+ add_header x-image-filter "c/w/$image_width/h/$image_height/q/$image_quality/s/$image_sharpen";
12
+
13
+ error_page 415 = /error.svg;
@@ -0,0 +1,13 @@
1
+ image_filter_buffer 16M;
2
+ image_filter rotate $image_rotate;
3
+ image_filter resize $image_width $image_height;
4
+ # FIXME: @wangshijun turn on this will improve jpeg and breaks png
5
+ image_filter_interlace on;
6
+ image_filter_transparency on;
7
+ image_filter_jpeg_quality $image_quality;
8
+ image_filter_webp_quality $image_quality;
9
+ image_filter_sharpen $image_sharpen;
10
+
11
+ add_header x-image-filter "r/w/$image_width/h/$image_height/q/$image_quality/s/$image_sharpen";
12
+
13
+ error_page 415 = /error.svg;
@@ -8,6 +8,7 @@ const shelljs = require('shelljs');
8
8
  const kill = require('fkill');
9
9
  const getPort = require('get-port');
10
10
  const uniqBy = require('lodash/uniqBy');
11
+ const camelCase = require('lodash/camelCase');
11
12
  const isEmpty = require('lodash/isEmpty');
12
13
  const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
13
14
  const {
@@ -38,6 +39,7 @@ const {
38
39
  getMainTemplate,
39
40
  getUpstreamName,
40
41
  joinNginxPath,
42
+ getDynamicModuleDirective,
41
43
  } = require('./util');
42
44
  const {
43
45
  decideHttpPort,
@@ -109,7 +111,9 @@ class NginxProvider extends BaseProvider {
109
111
  this.httpPort = decideHttpPort(httpPort);
110
112
  this.httpsPort = decideHttpsPort(httpsPort);
111
113
  this.cacheEnabled = !!cacheEnabled;
112
- this.isHttp2Supported = this._isHttp2Supported();
114
+
115
+ this.capabilities = this._checkCapabilities();
116
+
113
117
  this.conf = null; // nginx `conf` object
114
118
 
115
119
  logger.info('nginx provider config', {
@@ -142,6 +146,7 @@ class NginxProvider extends BaseProvider {
142
146
  cacheDir: this.getRelativeConfigDir(formatBackSlash(this.cacheDir)),
143
147
  workerProcess: this.getWorkerProcess(),
144
148
  nginxLoadModules: getNginxLoadModuleDirectives(REQUIRED_MODULES, this.readNginxConfigParams()).join(os.EOL),
149
+ capabilities: this.capabilities,
145
150
  });
146
151
  }
147
152
 
@@ -181,7 +186,7 @@ class NginxProvider extends BaseProvider {
181
186
  conf.on('flushed', () => resolve());
182
187
  conf.live(this.configPath);
183
188
 
184
- const { sites, configs: siteCorsConfigs } = formatRoutingTable(routingTable);
189
+ const { sites, configs: siteCorsConfigs } = formatRoutingTable(routingTable, this.capabilities);
185
190
 
186
191
  this._addCorsMap(conf, siteCorsConfigs);
187
192
  conf.nginx.http._add('server_tokens', 'off');
@@ -339,9 +344,31 @@ class NginxProvider extends BaseProvider {
339
344
  return result;
340
345
  }
341
346
 
342
- _isHttp2Supported() {
343
- const configArgs = this.readNginxConfigParams();
344
- return typeof configArgs['with-http_v2_module'] !== 'undefined';
347
+ _checkCapabilities() {
348
+ const config = this.readNginxConfigParams();
349
+ const capabilities = ['http_v2', 'http_image_filter', 'http_geoip'].reduce((acc, key) => {
350
+ const arg = `with-${key}_module`;
351
+ const capability = camelCase(key);
352
+
353
+ if (config[arg] === '') {
354
+ acc[capability] = 'static';
355
+ } else if (config[arg] === 'dynamic') {
356
+ acc[capability] = 'dynamic';
357
+ } else {
358
+ acc[capability] = false;
359
+ }
360
+
361
+ return acc;
362
+ }, {});
363
+
364
+ capabilities.modulesPath = config['modules-path'];
365
+ if (capabilities.modulesPath && getDynamicModuleDirective('httpBrotli', capabilities.modulesPath)) {
366
+ capabilities.httpBrotli = 'dynamic';
367
+ } else {
368
+ capabilities.httpBrotli = false;
369
+ }
370
+
371
+ return capabilities;
345
372
  }
346
373
 
347
374
  readNginxConfigParams() {
@@ -455,6 +482,7 @@ class NginxProvider extends BaseProvider {
455
482
  commonHeaders,
456
483
  cacheGroup,
457
484
  pageGroup,
485
+ filter,
458
486
  }) {
459
487
  server._add('location', concatPath(prefix, suffix));
460
488
 
@@ -489,6 +517,9 @@ class NginxProvider extends BaseProvider {
489
517
  location._add('proxy_cache_valid', `200 ${ROUTER_CACHE_GROUPS[cacheGroup].period}`);
490
518
  location._add('include', 'includes/cache');
491
519
  }
520
+ if (filter) {
521
+ location._add('include', `includes/image-filter-${filter}`);
522
+ }
492
523
 
493
524
  // Redirect blocklet traffic
494
525
  if (type === ROUTING_RULE_TYPES.BLOCKLET) {
@@ -515,8 +546,12 @@ class NginxProvider extends BaseProvider {
515
546
  }
516
547
 
517
548
  // Rewrite path
518
- location._add('rewrite', `^${rewritePathPrefix}/?(.*) /$1 break`);
519
- location._add('proxy_pass', `http://${getUpstreamName(process.env.ABT_NODE_SERVICE_PORT)}/`);
549
+ if (filter) {
550
+ location._add('rewrite', `^${rewritePathPrefix}/?(.*)/${filter}$ /$1 break`);
551
+ } else {
552
+ location._add('rewrite', `^${rewritePathPrefix}/?(.*) /$1 break`);
553
+ }
554
+ location._add('proxy_pass', `http://${getUpstreamName(process.env.ABT_NODE_SERVICE_PORT)}`);
520
555
 
521
556
  return;
522
557
  }
@@ -809,7 +844,7 @@ class NginxProvider extends BaseProvider {
809
844
  const crtPath = `${joinNginxPath(this.certDir, certificateFileName.replace('*', '-'))}.crt`;
810
845
  const keyPath = `${joinNginxPath(this.certDir, certificateFileName.replace('*', '-'))}.key`;
811
846
 
812
- let listen = `${this.httpsPort} ssl ${this.isHttp2Supported ? 'http2' : ''}`.trim();
847
+ let listen = `${this.httpsPort} ssl ${this.capabilities.httpV2 ? 'http2' : ''}`.trim();
813
848
  if (serverName === '_') {
814
849
  listen = `${listen} default_server`;
815
850
  }
@@ -1008,6 +1043,9 @@ NginxProvider.check = async ({ configDir = '' } = {}) => {
1008
1043
 
1009
1044
  return result;
1010
1045
  } catch (error) {
1046
+ if (process.env.DEBUG) {
1047
+ console.error(error);
1048
+ }
1011
1049
  result.available = false;
1012
1050
  result.error = error.message;
1013
1051
  logger.error('check nginx failed', { error });
package/lib/nginx/util.js CHANGED
@@ -147,6 +147,26 @@ const getWorkerConnectionCount = (maxWorkerConnections, workerProcess) => {
147
147
  return Math.min(maxWorkerConnections, Math.floor(ulimit / workerProcess));
148
148
  };
149
149
 
150
+ const getDynamicModuleDirective = (moduleName, modulesPath) => {
151
+ const mapping = {
152
+ httpImageFilter: ['ngx_http_image_filter_module.so'],
153
+ httpGeoip: ['ngx_http_geoip_module.so', 'ngx_stream_geoip_module.so'],
154
+ httpBrotli: ['ngx_http_brotli_filter_module.so', 'ngx_http_brotli_static_module.so'],
155
+ };
156
+
157
+ return mapping[moduleName]
158
+ .filter((x) => fs.existsSync(path.join(modulesPath, x)))
159
+ .map((x) => `load_module ${modulesPath}/${x};`)
160
+ .join(os.EOL);
161
+ };
162
+
163
+ const getDynamicModulesDirective = (capabilities) => {
164
+ return Object.keys(capabilities)
165
+ .filter((x) => capabilities[x] === 'dynamic')
166
+ .map((x) => getDynamicModuleDirective(x, capabilities.modulesPath))
167
+ .join(os.EOL);
168
+ };
169
+
150
170
  const getMainTemplate = ({
151
171
  logDir,
152
172
  tmpDir,
@@ -154,9 +174,10 @@ const getMainTemplate = ({
154
174
  nginxLoadModules = '',
155
175
  workerProcess,
156
176
  maxBodySize = CLIENT_MAX_BODY_SIZE,
177
+ capabilities = {},
157
178
  }) =>
158
- `
159
- ${nginxLoadModules}
179
+ `${nginxLoadModules}
180
+ ${getDynamicModulesDirective(capabilities)}
160
181
  worker_processes ${workerProcess};
161
182
  error_log /dev/null crit;
162
183
  user ${os.userInfo().username} ${getUserGroup(os.userInfo().username)};
@@ -192,10 +213,11 @@ http {
192
213
  include includes/params;
193
214
  include includes/mime.types;
194
215
  include includes/compression;
216
+ ${capabilities.httpImageFilter ? 'include includes/image-filter-args;' : ''}
195
217
 
196
218
  ${Object.keys(ROUTER_CACHE_GROUPS)
197
219
  .map((x) => getCachePathDirective(cacheDir, x))
198
- .join('\n')}
220
+ .join(os.EOL)}
199
221
  }
200
222
  `;
201
223
 
@@ -316,6 +338,8 @@ module.exports = {
316
338
  getUserGroup,
317
339
  getWorkerConnectionCount,
318
340
  getCachePathDirective,
341
+ getDynamicModuleDirective,
342
+ getDynamicModulesDirective,
319
343
  getUpstreamName,
320
344
  joinNginxPath,
321
345
  };
package/lib/util.js CHANGED
@@ -3,6 +3,7 @@ const fs = require('fs-extra');
3
3
  const path = require('path');
4
4
  const getPort = require('get-port');
5
5
  const portUsed = require('port-used');
6
+ const cloneDeep = require('lodash/cloneDeep');
6
7
  const sortBy = require('lodash/sortBy');
7
8
  const isValidDomain = require('is-valid-domain');
8
9
  const checkDomainMatch = require('@abtnode/util/lib/check-domain-match');
@@ -45,7 +46,7 @@ const concatPath = (prefix = '', suffix = '') => {
45
46
  return suffix ? `~* ^${prefix}.*${suffix}$` : prefix;
46
47
  };
47
48
 
48
- const formatRoutingTable = (routingTable, onRule) => {
49
+ const formatRoutingTable = (routingTable, capabilities = {}) => {
49
50
  const sites = {};
50
51
  const configs = [];
51
52
 
@@ -105,13 +106,24 @@ const formatRoutingTable = (routingTable, onRule) => {
105
106
  rule.pageGroup = x.to.pageGroup;
106
107
  }
107
108
 
108
- const tmpPath = concatPath(prefix, suffix);
109
- const tmpRules = sites[domain].rules;
110
- if (!tmpRules.find(({ prefix: p, suffix: s }) => concatPath(p, s) === tmpPath)) {
111
- sites[domain].rules.push(rule);
112
- if (typeof onRule === 'function') {
113
- onRule(sites[domain].rules, rule);
109
+ const addRule = (r) => {
110
+ const tmpPath = concatPath(r.prefix, r.suffix);
111
+ const tmpRules = sites[domain].rules;
112
+ if (!tmpRules.find(({ prefix: p, suffix: s }) => concatPath(p, s) === tmpPath)) {
113
+ sites[domain].rules.push(r);
114
114
  }
115
+ };
116
+
117
+ addRule(rule);
118
+
119
+ // add image filter rules for each cacheable path
120
+ if (capabilities.httpImageFilter && rule.cacheGroup) {
121
+ ['resize', 'crop'].forEach((filter) => {
122
+ const filterRule = cloneDeep(rule);
123
+ rule.filter = filter;
124
+ rule.suffix = `\\.(png|jpg|jpeg|gif|webp)/${filter}`;
125
+ addRule(filterRule);
126
+ });
115
127
  }
116
128
  });
117
129
 
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="300" height="200" viewBox="0 0 300 200"><rect width="100%" height="100%" fill="#DDDDDD"/><path fill="#999999" d="M112.5 94.58q0 5.4-1.79 10.01-1.78 4.61-5.05 7.97-3.26 3.37-7.85 5.26-4.59 1.88-10.2 1.88-5.58 0-10.17-1.88-4.59-1.89-7.87-5.26-3.28-3.36-5.08-7.97-1.8-4.61-1.8-10.01 0-5.41 1.8-10.02 1.8-4.6 5.08-7.97 3.28-3.36 7.87-5.25 4.59-1.89 10.17-1.89 3.74 0 7.04.87 3.29.87 6.05 2.45 2.75 1.58 4.94 3.84 2.2 2.26 3.73 5.05 1.53 2.79 2.33 6.05t.8 6.87Zm-9.35 0q0-4.05-1.09-7.26t-3.1-5.46q-2-2.24-4.88-3.43-2.87-1.19-6.47-1.19-3.61 0-6.48 1.19-2.87 1.19-4.9 3.43-2.02 2.25-3.11 5.46-1.08 3.21-1.08 7.26 0 4.04 1.08 7.26 1.09 3.21 3.11 5.44 2.03 2.22 4.9 3.41 2.87 1.19 6.48 1.19 3.6 0 6.47-1.19 2.88-1.19 4.88-3.41 2.01-2.23 3.1-5.44 1.09-3.22 1.09-7.26Zm31.51-10.85q3.88 0 7.06 1.26 3.18 1.26 5.44 3.57 2.26 2.31 3.48 5.64 1.23 3.34 1.23 7.45 0 4.15-1.23 7.48-1.22 3.33-3.48 5.68-2.26 2.34-5.44 3.6-3.18 1.26-7.06 1.26-3.91 0-7.1-1.26-3.2-1.26-5.46-3.6-2.26-2.35-3.5-5.68-1.24-3.33-1.24-7.48 0-4.11 1.24-7.45 1.24-3.33 3.5-5.64 2.26-2.31 5.46-3.57 3.19-1.26 7.1-1.26Zm0 29.48q4.36 0 6.45-2.92 2.09-2.93 2.09-8.57 0-5.65-2.09-8.6-2.09-2.96-6.45-2.96-4.42 0-6.54 2.97-2.13 2.98-2.13 8.59 0 5.61 2.13 8.55 2.12 2.94 6.54 2.94Zm32.03-18.73v15.64q1.43 1.73 3.11 2.44 1.69.72 3.66.72 1.9 0 3.43-.72 1.53-.71 2.6-2.17t1.65-3.69q.58-2.23.58-5.25 0-3.06-.49-5.19-.5-2.12-1.41-3.45-.92-1.33-2.23-1.94-1.31-.61-2.98-.61-2.61 0-4.45 1.1-1.84 1.11-3.47 3.12Zm-1.12-8.67.68 3.23q2.14-2.42 4.86-3.91 2.72-1.5 6.39-1.5 2.86 0 5.22 1.19 2.37 1.19 4.08 3.45 1.72 2.26 2.66 5.58.93 3.31.93 7.6 0 3.91-1.05 7.24-1.06 3.33-3.01 5.78-1.96 2.45-4.73 3.82-2.77 1.38-6.2 1.38-2.93 0-5-.9-2.08-.9-3.71-2.5v14.28h-8.4V84.28h5.14q1.63 0 2.14 1.53Zm54.54 2.24-1.91 3.03q-.34.54-.71.76-.38.22-.95.22-.62 0-1.31-.34-.7-.34-1.62-.76-.92-.43-2.09-.77t-2.77-.34q-2.48 0-3.89 1.06-1.41 1.05-1.41 2.75 0 1.12.73 1.89.73.76 1.93 1.34 1.21.58 2.74 1.04 1.53.46 3.11 1 1.58.54 3.11 1.24 1.53.7 2.74 1.77 1.21 1.07 1.94 2.57.73 1.49.73 3.6 0 2.52-.9 4.64-.9 2.13-2.67 3.67-1.77 1.55-4.37 2.42-2.6.86-6 .86-1.8 0-3.52-.32t-3.3-.9q-1.58-.58-2.92-1.36-1.34-.78-2.36-1.7l1.93-3.2q.38-.57.89-.88.51-.31 1.29-.31t1.48.45q.7.44 1.61.95.92.51 2.16.95 1.24.44 3.15.44 1.49 0 2.56-.36 1.08-.35 1.77-.93.7-.58 1.02-1.34.33-.77.33-1.58 0-1.23-.73-2.01-.74-.78-1.94-1.36-1.21-.58-2.76-1.04-1.54-.46-3.16-1-1.61-.54-3.16-1.27-1.55-.74-2.76-1.86-1.2-1.12-1.93-2.75t-.73-3.95q0-2.14.85-4.08.85-1.93 2.5-3.38 1.64-1.44 4.11-2.31 2.46-.87 5.69-.87 3.61 0 6.57 1.19 2.95 1.19 4.93 3.13ZM228.3 70h7.89v19.44q0 3.1-.31 6.07-.3 2.98-.78 6.31h-5.71q-.48-3.33-.78-6.31-.31-2.97-.31-6.07V70Zm-1.33 44.54q0-1.06.4-2.01.39-.95 1.08-1.63.7-.68 1.65-1.09.95-.41 2.04-.41 1.06 0 2.01.41.95.41 1.65 1.09.69.68 1.1 1.63.41.95.41 2.01 0 1.08-.41 2.02-.41.93-1.1 1.61-.7.68-1.65 1.08-.95.39-2.01.39-1.09 0-2.04-.39-.95-.4-1.65-1.08-.69-.68-1.08-1.61-.4-.94-.4-2.02Z"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abtnode/router-provider",
3
- "version": "1.16.14-beta-3127f514",
3
+ "version": "1.16.14-beta-c2843ec5",
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,10 +32,10 @@
32
32
  "url": "https://github.com/ArcBlock/blocklet-server/issues"
33
33
  },
34
34
  "dependencies": {
35
- "@abtnode/constant": "1.16.14-beta-3127f514",
36
- "@abtnode/logger": "1.16.14-beta-3127f514",
37
- "@abtnode/router-templates": "1.16.14-beta-3127f514",
38
- "@abtnode/util": "1.16.14-beta-3127f514",
35
+ "@abtnode/constant": "1.16.14-beta-c2843ec5",
36
+ "@abtnode/logger": "1.16.14-beta-c2843ec5",
37
+ "@abtnode/router-templates": "1.16.14-beta-c2843ec5",
38
+ "@abtnode/util": "1.16.14-beta-c2843ec5",
39
39
  "@arcblock/http-proxy": "^1.19.1",
40
40
  "axios": "^0.27.2",
41
41
  "debug": "^4.3.4",
@@ -59,5 +59,5 @@
59
59
  "bluebird": "^3.7.2",
60
60
  "fs-extra": "^10.1.0"
61
61
  },
62
- "gitHead": "cb397b94b752e71dfc0ba2c4ad08628cf03ce396"
62
+ "gitHead": "968bfad93779a21dd1374eede3ac7d4d6d40822b"
63
63
  }