@abtnode/router-provider 1.16.43-beta-20250424-125523-08a65a5c → 1.16.43-beta-20250427-132304-6da95c55
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/index.js +86 -8
- package/package.json +7 -6
package/lib/nginx/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const { NginxConfFile } = require('nginx-conf');
|
|
|
4
4
|
const fs = require('fs-extra');
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const fg = require('fast-glob');
|
|
7
|
+
const semver = require('semver');
|
|
7
8
|
const path = require('path');
|
|
8
9
|
const shelljs = require('shelljs');
|
|
9
10
|
const kill = require('fkill');
|
|
@@ -22,6 +23,8 @@ const {
|
|
|
22
23
|
USER_AVATAR_PATH_PREFIX,
|
|
23
24
|
LOG_RETAIN_IN_DAYS,
|
|
24
25
|
ROUTER_CACHE_GROUPS,
|
|
26
|
+
GATEWAY_RATE_LIMIT_GLOBAL,
|
|
27
|
+
GATEWAY_RATE_LIMIT,
|
|
25
28
|
} = require('@abtnode/constant');
|
|
26
29
|
|
|
27
30
|
const promiseRetry = require('promise-retry');
|
|
@@ -121,6 +124,7 @@ class NginxProvider extends BaseProvider {
|
|
|
121
124
|
this.capabilities = this._checkCapabilities();
|
|
122
125
|
|
|
123
126
|
this.conf = null; // nginx `conf` object
|
|
127
|
+
this.requestLimit = null;
|
|
124
128
|
|
|
125
129
|
logger.info('nginx provider config', {
|
|
126
130
|
configDir,
|
|
@@ -206,6 +210,7 @@ class NginxProvider extends BaseProvider {
|
|
|
206
210
|
this._addCommonResHeaders(conf.nginx.http, commonHeaders);
|
|
207
211
|
this._addExposeServices(conf, services);
|
|
208
212
|
if (requestLimit && requestLimit.enabled) {
|
|
213
|
+
this.requestLimit = requestLimit;
|
|
209
214
|
this.addRequestLimiting(conf.nginx.http, requestLimit);
|
|
210
215
|
}
|
|
211
216
|
if (blockPolicy && blockPolicy?.enabled) {
|
|
@@ -273,6 +278,8 @@ class NginxProvider extends BaseProvider {
|
|
|
273
278
|
this._addDefaultServer(conf, nodeInfo.port);
|
|
274
279
|
}
|
|
275
280
|
|
|
281
|
+
this._addStubStatusLocation(conf);
|
|
282
|
+
|
|
276
283
|
conf.flush();
|
|
277
284
|
});
|
|
278
285
|
});
|
|
@@ -366,7 +373,7 @@ class NginxProvider extends BaseProvider {
|
|
|
366
373
|
_checkCapabilities() {
|
|
367
374
|
const config = this.readNginxConfigParams();
|
|
368
375
|
|
|
369
|
-
const capabilities = ['http_v2', 'http_geoip'].reduce((acc, key) => {
|
|
376
|
+
const capabilities = ['http_v2', 'http_geoip', 'http_stub_status'].reduce((acc, key) => {
|
|
370
377
|
const arg = `with-${key}_module`;
|
|
371
378
|
const capability = camelCase(key);
|
|
372
379
|
|
|
@@ -393,6 +400,11 @@ class NginxProvider extends BaseProvider {
|
|
|
393
400
|
capabilities.modsecurity = modulePaths.some((x) => toLower(x).includes('modsecurity'));
|
|
394
401
|
}
|
|
395
402
|
|
|
403
|
+
const result = shelljs.exec(`${this.binPath} -v`, { silent: true });
|
|
404
|
+
if (result.code === 0) {
|
|
405
|
+
capabilities.version = semver.coerce((result.stderr || result.stdout).split('/').pop())?.version || '';
|
|
406
|
+
}
|
|
407
|
+
|
|
396
408
|
return capabilities;
|
|
397
409
|
}
|
|
398
410
|
|
|
@@ -791,14 +803,43 @@ class NginxProvider extends BaseProvider {
|
|
|
791
803
|
location._add('add_header', 'X-Request-ID $request_id');
|
|
792
804
|
}
|
|
793
805
|
|
|
806
|
+
_addStubStatusLocation(conf) {
|
|
807
|
+
if (!conf?.nginx?.http?.server) {
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
if (!this.capabilities?.httpStubStatus) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
const servers = Array.isArray(conf.nginx.http.server) ? conf.nginx.http.server : [conf.nginx.http.server];
|
|
816
|
+
const server = servers.find((x) => x.server_name._value === '127.0.0.1');
|
|
817
|
+
if (!server) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
server._add('location', '/__nginx_status');
|
|
822
|
+
const location = this._getLastLocation(server);
|
|
823
|
+
location._add('stub_status', 'on');
|
|
824
|
+
location._add('access_log', 'off');
|
|
825
|
+
location._add('allow', '127.0.0.1');
|
|
826
|
+
location._add('deny', 'all');
|
|
827
|
+
}
|
|
828
|
+
|
|
794
829
|
_getLastServer(conf) {
|
|
795
830
|
return conf.nginx.http.server.length
|
|
796
831
|
? conf.nginx.http.server[conf.nginx.http.server.length - 1]
|
|
797
832
|
: conf.nginx.http.server;
|
|
798
833
|
}
|
|
799
834
|
|
|
800
|
-
_getLastLocation(
|
|
801
|
-
|
|
835
|
+
_getLastLocation(server) {
|
|
836
|
+
const location = server.location.length ? server.location[server.location.length - 1] : server.location;
|
|
837
|
+
if (location && this.requestLimit?.enabled && !location.toString().includes('limit_req')) {
|
|
838
|
+
location._add('limit_req', `zone=ip_rate_limit burst=${this.requestLimit.burst} delay=10`);
|
|
839
|
+
location._add('limit_req', `zone=global_rate_limit burst=${this.requestLimit.burstGlobal} nodelay`);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
return location;
|
|
802
843
|
}
|
|
803
844
|
|
|
804
845
|
_getLastStreamServer(conf) {
|
|
@@ -843,7 +884,7 @@ class NginxProvider extends BaseProvider {
|
|
|
843
884
|
locations.forEach((x) => this._addReverseProxy({ server: httpsServerUnit, ...x, serverName, corsAllowedOrigins, commonHeaders, blockletDid })); // prettier-ignore
|
|
844
885
|
}
|
|
845
886
|
|
|
846
|
-
_addHttpServerUnit({ conf, serverName, port }) {
|
|
887
|
+
_addHttpServerUnit({ conf, serverName, port = '' }) {
|
|
847
888
|
let listen = port || this.httpPort;
|
|
848
889
|
if (serverName === '_') {
|
|
849
890
|
listen = `${listen} default_server`;
|
|
@@ -865,13 +906,24 @@ class NginxProvider extends BaseProvider {
|
|
|
865
906
|
const crtPath = `${joinNginxPath(this.certDir, certificateFileName.replace('*', '-'))}.crt`;
|
|
866
907
|
const keyPath = `${joinNginxPath(this.certDir, certificateFileName.replace('*', '-'))}.key`;
|
|
867
908
|
|
|
868
|
-
|
|
909
|
+
// Handle HTTP/2 configuration based on Nginx version
|
|
910
|
+
let listen = `${this.httpsPort} ssl`;
|
|
911
|
+
let http2Config = '';
|
|
912
|
+
if (this.capabilities.httpV2) {
|
|
913
|
+
if (this.capabilities.version && semver.gte(this.capabilities.version, '1.25.1')) {
|
|
914
|
+
http2Config = 'http2 on';
|
|
915
|
+
} else {
|
|
916
|
+
listen += ' http2';
|
|
917
|
+
}
|
|
918
|
+
}
|
|
869
919
|
if (serverName === '_') {
|
|
870
920
|
listen = `${listen} default_server`;
|
|
871
921
|
}
|
|
872
|
-
|
|
873
922
|
httpsServerUnit._add('server_name', serverName);
|
|
874
923
|
httpsServerUnit._add('listen', listen);
|
|
924
|
+
if (http2Config) {
|
|
925
|
+
httpsServerUnit._add('http2', 'on');
|
|
926
|
+
}
|
|
875
927
|
httpsServerUnit._add('ssl_certificate', crtPath);
|
|
876
928
|
httpsServerUnit._add('ssl_certificate_key', keyPath);
|
|
877
929
|
httpsServerUnit._add('include', 'includes/ssl');
|
|
@@ -958,8 +1010,34 @@ class NginxProvider extends BaseProvider {
|
|
|
958
1010
|
}
|
|
959
1011
|
|
|
960
1012
|
addRequestLimiting(block, limit) {
|
|
961
|
-
|
|
962
|
-
|
|
1013
|
+
if (!limit?.enabled) {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
const resourceExts =
|
|
1018
|
+
'jpg|jpeg|png|gif|webp|svg|ico|css|js|jsx|ts|tsx|mjs|woff|woff2|ttf|eot|otf|json|bmp|avif|wasm|xml|txt';
|
|
1019
|
+
|
|
1020
|
+
// limit by global
|
|
1021
|
+
block._addVerbatimBlock(
|
|
1022
|
+
'map $request_uri $global_rate_limit_key',
|
|
1023
|
+
`${os.EOL}${[`~*\\.(${resourceExts})$ "";`, 'default global_rate_limit;'].join(os.EOL)}${os.EOL}`
|
|
1024
|
+
);
|
|
1025
|
+
|
|
1026
|
+
// limit by ip
|
|
1027
|
+
block._addVerbatimBlock(
|
|
1028
|
+
'map $request_uri:$request_method $ip_rate_limit_key',
|
|
1029
|
+
`${os.EOL}${[`~*\\.(${resourceExts})(\\?.*)?: "";`, `~*:(${limit.methods.join('|')})$ ip_rate_limit;`, 'default "";'].join(os.EOL)}${os.EOL}`
|
|
1030
|
+
);
|
|
1031
|
+
|
|
1032
|
+
// link: https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone
|
|
1033
|
+
block._add(
|
|
1034
|
+
'limit_req_zone',
|
|
1035
|
+
`$global_rate_limit_key zone=global_rate_limit:128k rate=${limit.global || GATEWAY_RATE_LIMIT_GLOBAL.min}r/s`
|
|
1036
|
+
);
|
|
1037
|
+
block._add(
|
|
1038
|
+
'limit_req_zone',
|
|
1039
|
+
`$ip_rate_limit_key zone=ip_rate_limit:5m rate=${limit.rate || GATEWAY_RATE_LIMIT.min}r/s`
|
|
1040
|
+
);
|
|
963
1041
|
block._add('limit_req_status', 429);
|
|
964
1042
|
}
|
|
965
1043
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/router-provider",
|
|
3
|
-
"version": "1.16.43-beta-
|
|
3
|
+
"version": "1.16.43-beta-20250427-132304-6da95c55",
|
|
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.43-beta-
|
|
36
|
-
"@abtnode/logger": "1.16.43-beta-
|
|
37
|
-
"@abtnode/router-templates": "1.16.43-beta-
|
|
38
|
-
"@abtnode/util": "1.16.43-beta-
|
|
35
|
+
"@abtnode/constant": "1.16.43-beta-20250427-132304-6da95c55",
|
|
36
|
+
"@abtnode/logger": "1.16.43-beta-20250427-132304-6da95c55",
|
|
37
|
+
"@abtnode/router-templates": "1.16.43-beta-20250427-132304-6da95c55",
|
|
38
|
+
"@abtnode/util": "1.16.43-beta-20250427-132304-6da95c55",
|
|
39
39
|
"@arcblock/http-proxy": "^1.19.1",
|
|
40
40
|
"@arcblock/is-valid-domain": "^1.0.5",
|
|
41
41
|
"axios": "^1.7.9",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"object-hash": "^3.0.0",
|
|
52
52
|
"port-used": "^2.0.8",
|
|
53
53
|
"promise-retry": "^2.0.1",
|
|
54
|
+
"semver": "^7.6.3",
|
|
54
55
|
"shelljs": "^0.8.5",
|
|
55
56
|
"tar": "^6.1.11",
|
|
56
57
|
"ufo": "^1.5.3",
|
|
@@ -60,5 +61,5 @@
|
|
|
60
61
|
"bluebird": "^3.7.2",
|
|
61
62
|
"fs-extra": "^11.2.0"
|
|
62
63
|
},
|
|
63
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "9df10dcb3135a528912241e7fc1ed54171bfeb03"
|
|
64
65
|
}
|