egg 3.3.2 → 3.4.0-beta.0
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/History.md +2083 -0
- package/app/middleware/meta.js +0 -16
- package/config/config.default.js +4 -0
- package/index.js +0 -2
- package/lib/core/context_httpclient.js +4 -6
- package/lib/core/dnscache_httpclient.js +8 -37
- package/lib/core/httpclient.js +10 -44
- package/lib/core/httpclient_next.js +0 -2
- package/lib/egg.js +13 -7
- package/package.json +4 -6
package/app/middleware/meta.js
CHANGED
|
@@ -2,15 +2,9 @@
|
|
|
2
2
|
* meta middleware, should be the first middleware
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
5
|
const { performance } = require('perf_hooks');
|
|
8
|
-
const semver = require('semver');
|
|
9
6
|
|
|
10
7
|
module.exports = options => {
|
|
11
|
-
// Node.js >=14.8.0 and >= 12.19.0 will set Keep-Alive Header, see https://github.com/nodejs/node/pull/34561
|
|
12
|
-
const shouldPatchKeepAliveHeader = !semver.satisfies(process.version, '>=14.8.0 || ^12.19.0');
|
|
13
|
-
|
|
14
8
|
return async function meta(ctx, next) {
|
|
15
9
|
if (options.logging) {
|
|
16
10
|
ctx.coreLogger.info('[meta] request started, host: %s, user-agent: %s', ctx.host, ctx.header['user-agent']);
|
|
@@ -22,15 +16,5 @@ module.exports = options => {
|
|
|
22
16
|
} else {
|
|
23
17
|
ctx.set('x-readtime', Date.now() - ctx.starttime);
|
|
24
18
|
}
|
|
25
|
-
|
|
26
|
-
// try to support Keep-Alive Header when < 14.8.0
|
|
27
|
-
const server = ctx.app.server;
|
|
28
|
-
if (shouldPatchKeepAliveHeader && server && server.keepAliveTimeout && server.keepAliveTimeout >= 1000 && ctx.header.connection !== 'close') {
|
|
29
|
-
/**
|
|
30
|
-
* use Math.floor instead of parseInt. More: https://github.com/eggjs/egg/pull/2702
|
|
31
|
-
*/
|
|
32
|
-
const timeout = Math.floor(server.keepAliveTimeout / 1000);
|
|
33
|
-
ctx.set('keep-alive', `timeout=${timeout}`);
|
|
34
|
-
}
|
|
35
19
|
};
|
|
36
20
|
};
|
package/config/config.default.js
CHANGED
|
@@ -152,6 +152,10 @@ module.exports = appInfo => {
|
|
|
152
152
|
// ignore any key contains "secret" keyword
|
|
153
153
|
/secret/i,
|
|
154
154
|
]),
|
|
155
|
+
timing: {
|
|
156
|
+
// if boot action >= slowBootActionMinDuration, egg core will print it to warnning log
|
|
157
|
+
slowBootActionMinDuration: 5000,
|
|
158
|
+
},
|
|
155
159
|
},
|
|
156
160
|
|
|
157
161
|
/**
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
class ContextHttpClient {
|
|
4
2
|
constructor(ctx) {
|
|
5
3
|
this.ctx = ctx;
|
|
@@ -14,14 +12,14 @@ class ContextHttpClient {
|
|
|
14
12
|
* @param {Object} [options] - options for request.
|
|
15
13
|
* @return {Object} see {@link Application#curl}
|
|
16
14
|
*/
|
|
17
|
-
curl(url, options) {
|
|
15
|
+
async curl(url, options) {
|
|
18
16
|
options = options || {};
|
|
19
17
|
options.ctx = this.ctx;
|
|
20
|
-
return this.app.curl(url, options);
|
|
18
|
+
return await this.app.curl(url, options);
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
request(url, options) {
|
|
24
|
-
return this.curl(url, options);
|
|
21
|
+
async request(url, options) {
|
|
22
|
+
return await this.curl(url, options);
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
25
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const dns = require('mz/dns');
|
|
1
|
+
const dns = require('dns').promises;
|
|
4
2
|
const LRU = require('ylru');
|
|
5
3
|
const HttpClient = require('./httpclient');
|
|
6
4
|
const utility = require('utility');
|
|
@@ -17,39 +15,13 @@ class DNSCacheHttpClient extends HttpClient {
|
|
|
17
15
|
this.dnsCache = new LRU(this.app.config.httpclient.dnsCacheMaxLength);
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
request(url, args
|
|
21
|
-
// request
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
args = null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// the callback style
|
|
28
|
-
if (callback) {
|
|
29
|
-
this.app.deprecate('[dnscache_httpclient] We now support async for this function, so callback isn\'t recommended.');
|
|
30
|
-
// disable dns cache in request by args handle
|
|
31
|
-
if (args && args.enableDNSCache === false) {
|
|
32
|
-
super.request(url, args, callback);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
this[DNSLOOKUP](url, args)
|
|
36
|
-
.then(result => {
|
|
37
|
-
return super.request(result.url, result.args);
|
|
38
|
-
})
|
|
39
|
-
.then(result => process.nextTick(() => callback(null, result.data, result.res)))
|
|
40
|
-
.catch(err => process.nextTick(() => callback(err)));
|
|
41
|
-
return;
|
|
18
|
+
async request(url, args) {
|
|
19
|
+
// disable dns cache in request by args handle
|
|
20
|
+
if (args && args.enableDNSCache === false) {
|
|
21
|
+
return await super.request(url, args);
|
|
42
22
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return (async () => {
|
|
46
|
-
// disable dns cache in request by args handle
|
|
47
|
-
if (args && args.enableDNSCache === false) {
|
|
48
|
-
return super.request(url, args);
|
|
49
|
-
}
|
|
50
|
-
const result = await this[DNSLOOKUP](url, args);
|
|
51
|
-
return super.request(result.url, result.args);
|
|
52
|
-
})();
|
|
23
|
+
const result = await this[DNSLOOKUP](url, args);
|
|
24
|
+
return await super.request(result.url, result.args);
|
|
53
25
|
}
|
|
54
26
|
|
|
55
27
|
async [DNSLOOKUP](url, args) {
|
|
@@ -96,7 +68,7 @@ class DNSCacheHttpClient extends HttpClient {
|
|
|
96
68
|
async [UPDATE_DNS](hostname, args) {
|
|
97
69
|
const logger = args.ctx ? args.ctx.coreLogger : this.app.coreLogger;
|
|
98
70
|
try {
|
|
99
|
-
const
|
|
71
|
+
const { address } = await dns.lookup(hostname, { family: 4 });
|
|
100
72
|
logger.info('[dnscache_httpclient] dns lookup success: %s => %s',
|
|
101
73
|
hostname, address);
|
|
102
74
|
this.dnsCache.set(hostname, { timestamp: Date.now(), ip: address });
|
|
@@ -106,7 +78,6 @@ class DNSCacheHttpClient extends HttpClient {
|
|
|
106
78
|
throw err;
|
|
107
79
|
}
|
|
108
80
|
}
|
|
109
|
-
|
|
110
81
|
}
|
|
111
82
|
|
|
112
83
|
module.exports = DNSCacheHttpClient;
|
package/lib/core/httpclient.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const Agent = require('agentkeepalive');
|
|
4
2
|
const HttpsAgent = require('agentkeepalive').HttpsAgent;
|
|
5
3
|
const urllib = require('urllib');
|
|
@@ -25,58 +23,26 @@ class HttpClient extends urllib.HttpClient2 {
|
|
|
25
23
|
this.app = app;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
request(url, args
|
|
29
|
-
if (typeof args === 'function') {
|
|
30
|
-
callback = args;
|
|
31
|
-
args = null;
|
|
32
|
-
}
|
|
33
|
-
|
|
26
|
+
async request(url, args) {
|
|
34
27
|
args = args || {};
|
|
35
|
-
|
|
36
28
|
if (args.ctx && args.ctx.tracer) {
|
|
37
29
|
args.tracer = args.ctx.tracer;
|
|
38
30
|
} else {
|
|
39
31
|
args.tracer = args.tracer || this.app.tracer;
|
|
40
32
|
}
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
try {
|
|
35
|
+
return await super.request(url, args);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
if (err.code === 'ENETUNREACH') {
|
|
38
|
+
throw HttpClientError.create(err.message, err.code);
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
49
41
|
}
|
|
50
|
-
|
|
51
|
-
// the Promise style
|
|
52
|
-
return super.request(url, args)
|
|
53
|
-
.catch(err => {
|
|
54
|
-
if (err.code === 'ENETUNREACH') {
|
|
55
|
-
throw HttpClientError.create(err.message, err.code);
|
|
56
|
-
}
|
|
57
|
-
throw err;
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
curl(url, args, callback) {
|
|
62
|
-
return this.request(url, args, callback);
|
|
63
42
|
}
|
|
64
43
|
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
return callback => {
|
|
68
|
-
this.request(url, args, (err, data, res) => {
|
|
69
|
-
if (err) {
|
|
70
|
-
return callback(err);
|
|
71
|
-
}
|
|
72
|
-
callback(null, {
|
|
73
|
-
data,
|
|
74
|
-
status: res.status,
|
|
75
|
-
headers: res.headers,
|
|
76
|
-
res,
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
};
|
|
44
|
+
async curl(...args) {
|
|
45
|
+
return await this.request(...args);
|
|
80
46
|
}
|
|
81
47
|
}
|
|
82
48
|
|
package/lib/egg.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const { performance } = require('perf_hooks');
|
|
4
2
|
const path = require('path');
|
|
5
3
|
const fs = require('fs');
|
|
@@ -52,6 +50,7 @@ class EggApplication extends EggCore {
|
|
|
52
50
|
this.ContextLogger = ContextLogger;
|
|
53
51
|
this.ContextHttpClient = ContextHttpClient;
|
|
54
52
|
this.HttpClient = HttpClient;
|
|
53
|
+
this.HttpClientNext = HttpClientNext;
|
|
55
54
|
|
|
56
55
|
this.loader.loadConfig();
|
|
57
56
|
|
|
@@ -281,8 +280,8 @@ class EggApplication extends EggCore {
|
|
|
281
280
|
* console.log(result.status, result.headers, result.data);
|
|
282
281
|
* ```
|
|
283
282
|
*/
|
|
284
|
-
curl(url, opts) {
|
|
285
|
-
return this.httpclient.request(url, opts);
|
|
283
|
+
async curl(url, opts) {
|
|
284
|
+
return await this.httpclient.request(url, opts);
|
|
286
285
|
}
|
|
287
286
|
|
|
288
287
|
/**
|
|
@@ -293,7 +292,7 @@ class EggApplication extends EggCore {
|
|
|
293
292
|
get httpclient() {
|
|
294
293
|
if (!this[HTTPCLIENT]) {
|
|
295
294
|
if (this.config.httpclient.useHttpClientNext) {
|
|
296
|
-
this[HTTPCLIENT] = new HttpClientNext(this);
|
|
295
|
+
this[HTTPCLIENT] = new this.HttpClientNext(this);
|
|
297
296
|
} else if (this.config.httpclient.enableDNSCache) {
|
|
298
297
|
this[HTTPCLIENT] = new DNSCacheHttpClient(this);
|
|
299
298
|
} else {
|
|
@@ -411,12 +410,19 @@ class EggApplication extends EggCore {
|
|
|
411
410
|
|
|
412
411
|
dumpTiming() {
|
|
413
412
|
try {
|
|
414
|
-
const
|
|
413
|
+
const items = this.timing.toJSON();
|
|
415
414
|
const rundir = this.config.rundir;
|
|
416
415
|
const dumpFile = path.join(rundir, `${this.type}_timing_${process.pid}.json`);
|
|
417
|
-
fs.writeFileSync(dumpFile, CircularJSON.stringify(
|
|
416
|
+
fs.writeFileSync(dumpFile, CircularJSON.stringify(items, null, 2));
|
|
418
417
|
// only disable, not clear bootstrap timing data.
|
|
419
418
|
this.timing.disable();
|
|
419
|
+
// show duration >= ${slowBootActionMinDuration}ms action to warnning log
|
|
420
|
+
for (const item of items) {
|
|
421
|
+
if (item.duration >= this.config.dump.timing.slowBootActionMinDuration) {
|
|
422
|
+
this.coreLogger.warn('[egg:core][slow-boot-action] #%d %dms, name: %s',
|
|
423
|
+
item.index, item.duration, item.name);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
420
426
|
} catch (err) {
|
|
421
427
|
this.coreLogger.warn(`dumpTiming error: ${err.message}`);
|
|
422
428
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "egg",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0-beta.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"tag": "test"
|
|
6
|
+
},
|
|
4
7
|
"description": "A web framework's framework for Node.js",
|
|
5
8
|
"keywords": [
|
|
6
9
|
"web",
|
|
@@ -48,9 +51,7 @@
|
|
|
48
51
|
"koa-is-json": "^1.0.0",
|
|
49
52
|
"koa-override": "^3.0.0",
|
|
50
53
|
"ms": "^2.1.3",
|
|
51
|
-
"mz": "^2.7.0",
|
|
52
54
|
"on-finished": "^2.4.1",
|
|
53
|
-
"semver": "^7.3.7",
|
|
54
55
|
"sendmessage": "^1.1.0",
|
|
55
56
|
"urllib": "^2.33.0",
|
|
56
57
|
"urllib-next": "^3.1.3",
|
|
@@ -68,7 +69,6 @@
|
|
|
68
69
|
"coffee": "^5.4.0",
|
|
69
70
|
"dumi": "^1.1.47",
|
|
70
71
|
"dumi-theme-egg": "^1.2.2",
|
|
71
|
-
"egg-alinode": "^2.0.1",
|
|
72
72
|
"egg-bin": "^5",
|
|
73
73
|
"egg-mock": "^4.2.1",
|
|
74
74
|
"egg-plugin-puml": "^2.4.0",
|
|
@@ -81,8 +81,6 @@
|
|
|
81
81
|
"jsdoc": "^3.6.11",
|
|
82
82
|
"koa": "^2.13.4",
|
|
83
83
|
"koa-static": "^5.0.0",
|
|
84
|
-
"mz": "^2.7.0",
|
|
85
|
-
"mz-modules": "^2.1.0",
|
|
86
84
|
"pedding": "^1.1.0",
|
|
87
85
|
"prettier": "^2.7.1",
|
|
88
86
|
"runscript": "^1.5.3",
|