From f9c1e8948d1c6cf0f4ef60d5896645b53d7bfcfd Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Sun, 15 Sep 2024 13:59:03 +0800 Subject: [PATCH 1/5] feat: support allowH2 on urllib@4 https://github.com/eggjs/egg/issues/5347 --- config/config.default.js | 4 +- lib/core/httpclient4.js | 38 ++++++++++++++ lib/egg.js | 12 ++++- package.json | 6 +-- test/doc.test.js | 41 --------------- .../app.js | 6 +-- .../config/config.default.js | 4 +- .../apps/httpclient-allowH2/package.json | 3 ++ .../apps/httpclient-http2/package.json | 3 -- test/fixtures/apps/httpclient-tracer/app.js | 4 +- test/lib/core/httpclient.test.js | 52 +++++++++++++++---- 11 files changed, 104 insertions(+), 69 deletions(-) create mode 100644 lib/core/httpclient4.js delete mode 100644 test/doc.test.js rename test/fixtures/apps/{httpclient-http2 => httpclient-allowH2}/app.js (77%) rename test/fixtures/apps/{httpclient-http2 => httpclient-allowH2}/config/config.default.js (55%) create mode 100644 test/fixtures/apps/httpclient-allowH2/package.json delete mode 100644 test/fixtures/apps/httpclient-http2/package.json diff --git a/config/config.default.js b/config/config.default.js index 53a913a20a..534fba9891 100644 --- a/config/config.default.js +++ b/config/config.default.js @@ -303,8 +303,8 @@ module.exports = appInfo => { * @property {Number} httpsAgent.freeSocketTimeout - httpss agent socket keepalive max free time, default is 4000 ms. * @property {Number} httpsAgent.maxSockets - https agent max socket number of one host, default is `Number.MAX_SAFE_INTEGER` @ses https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER * @property {Number} httpsAgent.maxFreeSockets - https agent max free socket number of one host, default is 256. - * @property {Boolean} useHttpClientNext - use urllib@3 HttpClient - * @property {Boolean} allowH2 - Allow to use HTTP2 first, only work on `useHttpClientNext = true` + * @property {Boolean} useHttpClientNext - use urllib@3 HttpClient, default is false + * @property {Boolean} allowH2 - use urllib@4 HttpClient and enable H2, default is false. Only works on Node.js >= 18 */ config.httpclient = { enableDNSCache: false, diff --git a/lib/core/httpclient4.js b/lib/core/httpclient4.js new file mode 100644 index 0000000000..7d8134f0c2 --- /dev/null +++ b/lib/core/httpclient4.js @@ -0,0 +1,38 @@ +const { HttpClient } = require('urllib4'); +const ms = require('humanize-ms'); + +class HttpClient4 extends HttpClient { + constructor(app) { + normalizeConfig(app); + const config = app.config.httpclient; + super({ + app, + defaultArgs: config.request, + allowH2: config.allowH2, + }); + this.app = app; + } + + async request(url, options) { + options = options || {}; + if (options.ctx && options.ctx.tracer) { + options.tracer = options.ctx.tracer; + } else { + options.tracer = options.tracer || this.app.tracer; + } + return await super.request(url, options); + } + + async curl(...args) { + return await this.request(...args); + } +} + +function normalizeConfig(app) { + const config = app.config.httpclient; + if (typeof config.request.timeout === 'string') { + config.request.timeout = ms(config.request.timeout); + } +} + +module.exports = HttpClient4; diff --git a/lib/egg.js b/lib/egg.js index a70c69fae8..9bcf24c666 100644 --- a/lib/egg.js +++ b/lib/egg.js @@ -20,6 +20,13 @@ const utils = require('./core/utils'); const BaseContextClass = require('./core/base_context_class'); const BaseHookClass = require('./core/base_hook_class'); +let HttpClient4 = HttpClientNext; +const mainNodejsVersion = parseInt(process.versions.node.split('.')[0]); +if (mainNodejsVersion >= 18) { + // urllib@4 only works on Node.js >= 18 + HttpClient4 = require('./core/httpclient4'); +} + const HTTPCLIENT = Symbol('EggApplication#httpclient'); const LOGGERS = Symbol('EggApplication#loggers'); const EGG_PATH = Symbol.for('egg#eggPath'); @@ -51,6 +58,7 @@ class EggApplication extends EggCore { this.ContextHttpClient = ContextHttpClient; this.HttpClient = HttpClient; this.HttpClientNext = HttpClientNext; + this.HttpClient4 = HttpClient4; this.loader.loadConfig(); @@ -292,7 +300,9 @@ class EggApplication extends EggCore { */ createHttpClient(options) { let httpClient; - if (this.config.httpclient.useHttpClientNext) { + if (this.config.httpclient.allowH2) { + httpClient = new this.HttpClient4(this); + } else if (this.config.httpclient.useHttpClientNext) { httpClient = new this.HttpClientNext(this, options); } else if (this.config.httpclient.enableDNSCache) { httpClient = new DNSCacheHttpClient(this, options); diff --git a/package.json b/package.json index 734fbdb851..48bbb375f1 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,8 @@ "onelogger": "^1.0.0", "sendmessage": "^2.0.0", "urllib": "^2.33.0", - "urllib-next": "npm:urllib@^3.26.0", + "urllib-next": "npm:urllib@^3.27.1", + "urllib4": "npm:urllib@^4.3.0", "utility": "^2.1.0", "ylru": "^1.3.2" }, @@ -77,7 +78,6 @@ "egg-view-nunjucks": "^2.3.0", "eslint": "^8.23.1", "eslint-config-egg": "^12.0.0", - "findlinks": "^2.2.0", "formstream": "^1.1.1", "jsdoc": "^3.6.11", "koa": "^2.13.4", @@ -85,11 +85,9 @@ "node-libs-browser": "^2.2.1", "pedding": "^1.1.0", "prettier": "^2.7.1", - "puppeteer": "^19.11.1", "react": "^16.14.0", "react-dom": "^16.14.0", "react-router": "^5.3.4", - "runscript": "^1.5.3", "sdk-base": "^4.2.1", "spy": "^1.0.0", "supertest": "^6.2.4", diff --git a/test/doc.test.js b/test/doc.test.js deleted file mode 100644 index de53ea206b..0000000000 --- a/test/doc.test.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -const path = require('path'); -const findlinks = require('findlinks'); -const assert = require('assert'); -const runscript = require('runscript'); -const utils = require('./utils'); -const puppeteer = require('puppeteer'); - -describe('test/doc.test.js', () => { - /** - * This unit test is ONLY working for the latest nodejs version (v18.0.0) - * or higher version, bcoz on windows, it takes quite a lot of time - * to generate the whole doc. We only need some of the test cases to check - * whether the links inside the doc gets fine or not. - */ - it('should have no broken urls (based on non-windows platform and node\'s version >=18)', async function() { - - const mainNodejsVersion = parseInt(process.versions.node.split('.')[0]); - - if (process.platform === 'linux' && mainNodejsVersion >= 18) { - const cwd = path.dirname(__dirname); - const dumi = path.join(cwd, 'node_modules', '.bin', 'dumi'); - await runscript(`cross-env NODE_OPTIONS=--openssl-legacy-provider APP_ROOT=./site ${dumi} build`, - { - cwd, - }); - const app = utils.cluster({ - baseDir: 'apps/docapp', - }); - app.coverage(false); - await app.ready(); - const result = await findlinks({ src: app.url, logger: console, puppeteer }); - if (result.fail !== 0) console.log(result); - assert(result.fail === 0); - app.close(); - } else { - this.skip(); - } - }).timeout(10 * 60 * 1000); -}); diff --git a/test/fixtures/apps/httpclient-http2/app.js b/test/fixtures/apps/httpclient-allowH2/app.js similarity index 77% rename from test/fixtures/apps/httpclient-http2/app.js rename to test/fixtures/apps/httpclient-allowH2/app.js index 29c5a62b35..5af2297350 100644 --- a/test/fixtures/apps/httpclient-http2/app.js +++ b/test/fixtures/apps/httpclient-allowH2/app.js @@ -1,9 +1,7 @@ -'use strict'; - const assert = require('assert'); module.exports = app => { - class CustomHttpClient extends app.HttpClientNext { + class CustomHttpClient extends app.HttpClient4 { request(url, opt) { return new Promise(resolve => { assert(/^http/.test(url), 'url should start with http, but got ' + url); @@ -17,5 +15,5 @@ module.exports = app => { return this.request(url, opt); } } - app.HttpClientNext = CustomHttpClient; + app.HttpClient4 = CustomHttpClient; }; diff --git a/test/fixtures/apps/httpclient-http2/config/config.default.js b/test/fixtures/apps/httpclient-allowH2/config/config.default.js similarity index 55% rename from test/fixtures/apps/httpclient-http2/config/config.default.js rename to test/fixtures/apps/httpclient-allowH2/config/config.default.js index 77834b89ad..e477cdb9db 100644 --- a/test/fixtures/apps/httpclient-http2/config/config.default.js +++ b/test/fixtures/apps/httpclient-allowH2/config/config.default.js @@ -1,4 +1,6 @@ exports.httpclient = { - useHttpClientNext: true, allowH2: true, + request: { + timeout: 99, + }, }; diff --git a/test/fixtures/apps/httpclient-allowH2/package.json b/test/fixtures/apps/httpclient-allowH2/package.json new file mode 100644 index 0000000000..d788b7620b --- /dev/null +++ b/test/fixtures/apps/httpclient-allowH2/package.json @@ -0,0 +1,3 @@ +{ + "name": "httpclient-allowH2" +} diff --git a/test/fixtures/apps/httpclient-http2/package.json b/test/fixtures/apps/httpclient-http2/package.json deleted file mode 100644 index 56b5d28da8..0000000000 --- a/test/fixtures/apps/httpclient-http2/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "httpclient-overwrite" -} diff --git a/test/fixtures/apps/httpclient-tracer/app.js b/test/fixtures/apps/httpclient-tracer/app.js index 0b6d6e866c..80fd82b24c 100644 --- a/test/fixtures/apps/httpclient-tracer/app.js +++ b/test/fixtures/apps/httpclient-tracer/app.js @@ -28,14 +28,14 @@ module.exports = app => { }); assert(res.status === 200); - res = await httpclient.request('https://github.com', { + res = await httpclient.request('https://registry.npmmirror.com', { method: 'GET', timeout: 20000, }); assert(res.status === 200); - res = await httpclient.request('https://www.npmjs.com', { + res = await httpclient.request('https://npmmirror.com', { method: 'GET', timeout: 20000, }); diff --git a/test/lib/core/httpclient.test.js b/test/lib/core/httpclient.test.js index e0b26b0da3..f0ad78d222 100644 --- a/test/lib/core/httpclient.test.js +++ b/test/lib/core/httpclient.test.js @@ -1,5 +1,4 @@ const assert = require('node:assert'); -const { sensitiveHeaders } = require('node:http2'); const mm = require('egg-mock'); const urllib = require('urllib'); const Httpclient = require('../../../lib/core/httpclient'); @@ -305,7 +304,7 @@ describe('test/lib/core/httpclient.test.js', () => { describe('overwrite httpclient support allowH2=true', () => { let app; before(() => { - app = utils.app('apps/httpclient-http2'); + app = utils.app('apps/httpclient-allowH2'); return app.ready(); }); after(() => app.close()); @@ -314,21 +313,52 @@ describe('test/lib/core/httpclient.test.js', () => { const res = await app.httpclient.request(url); assert.equal(res.status, 200); assert.equal(res.data.toString(), 'GET /'); - assert.equal(sensitiveHeaders in res.headers, false); + // assert.equal(sensitiveHeaders in res.headers, false); const res2 = await app.httpclient.request('https://registry.npmmirror.com/urllib/latest', { dataType: 'json', }); assert.equal(res2.status, 200); assert.equal(res2.data.name, 'urllib'); - assert.equal(sensitiveHeaders in res2.headers, true); + // assert.equal(sensitiveHeaders in res2.headers, true); }); - it('should assert url', () => { - return app.httpclient.curl('unknown url') - .catch(err => { - assert(err); - assert(err.message.includes('url should start with http, but got unknown url')); + it('should set request default global timeout to 99ms', async () => { + await assert.rejects(async () => { + await app.httpclient.curl(`${url}/timeout`); + }, err => { + assert.equal(err.name, 'HttpClientRequestTimeoutError'); + assert(err.message.includes('Request timeout for 99 ms')); + return true; + }); + }); + + it('should request http1.1 success', async () => { + const result = await app.httpclient.curl(`${url}`, { + dataType: 'text', + }); + assert.equal(result.status, 200); + assert.equal(result.data, 'GET /'); + }); + + it('should request http2 success', async () => { + for (let i = 0; i < 10; i++) { + const result = await app.httpclient.curl('https://registry.npmmirror.com', { + dataType: 'json', + timeout: 5000, }); + assert.equal(result.status, 200); + assert.equal(result.headers['content-type'], 'application/json; charset=utf-8'); + assert.equal(result.data.sync_model, 'all'); + } + }); + + it('should assert url', async () => { + await assert.rejects(async () => { + await app.httpclient.curl('unknown url'); + }, err => { + assert.match(err.message, /url should start with http, but got unknown url/); + return true; + }); }); }); @@ -618,13 +648,13 @@ describe('test/lib/core/httpclient.test.js', () => { }); assert(res.status === 200); - res = await httpclient.request('https://github.com', { + res = await httpclient.request('https://registry.npmmirror.com', { method: 'GET', timeout: 20000, }); assert(res.status === 200); - res = await httpclient.request('https://www.npmjs.com', { + res = await httpclient.request('https://npmmirror.com', { method: 'GET', timeout: 20000, }); From e9d5b9958ab4047e88fbf14576bbe1cca735ca02 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Sun, 15 Sep 2024 18:25:14 +0800 Subject: [PATCH 2/5] f --- lib/core/httpclient4.js | 31 +++++++++++++++++++++++++++---- lib/egg.js | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/core/httpclient4.js b/lib/core/httpclient4.js index 7d8134f0c2..2ec166a22e 100644 --- a/lib/core/httpclient4.js +++ b/lib/core/httpclient4.js @@ -1,14 +1,22 @@ const { HttpClient } = require('urllib4'); const ms = require('humanize-ms'); +const SSRF_HTTPCLIENT = Symbol('SSRF_HTTPCLIENT'); class HttpClient4 extends HttpClient { - constructor(app) { + constructor(app, options) { normalizeConfig(app); - const config = app.config.httpclient; + options = options || {}; + options = { + ...app.config.httpclient, + ...options, + }; super({ app, - defaultArgs: config.request, - allowH2: config.allowH2, + defaultArgs: options.request, + allowH2: options.allowH2, + // use on egg-security ssrf + // https://github.com/eggjs/egg-security/blob/master/lib/extend/safe_curl.js#L11 + checkAddress: options.checkAddress, }); this.app = app; } @@ -26,6 +34,21 @@ class HttpClient4 extends HttpClient { async curl(...args) { return await this.request(...args); } + + async safeCurl(url, options = {}) { + if (!this[SSRF_HTTPCLIENT]) { + const ssrfConfig = this.app.config.security.ssrf; + if (ssrfConfig?.checkAddress) { + options.checkAddress = ssrfConfig.checkAddress; + } else { + this.app.logger.warn('[egg-security] please configure `config.security.ssrf` first'); + } + this[SSRF_HTTPCLIENT] = new HttpClient4(this.app, { + checkAddress: ssrfConfig.checkAddress, + }); + } + return await this[SSRF_HTTPCLIENT].request(url, options); + } } function normalizeConfig(app) { diff --git a/lib/egg.js b/lib/egg.js index 9bcf24c666..33ed380152 100644 --- a/lib/egg.js +++ b/lib/egg.js @@ -301,7 +301,7 @@ class EggApplication extends EggCore { createHttpClient(options) { let httpClient; if (this.config.httpclient.allowH2) { - httpClient = new this.HttpClient4(this); + httpClient = new this.HttpClient4(this, options); } else if (this.config.httpclient.useHttpClientNext) { httpClient = new this.HttpClientNext(this, options); } else if (this.config.httpclient.enableDNSCache) { From e206b1d815ac324d2fff0c212e0d68a029cb9e8f Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Sun, 15 Sep 2024 18:42:23 +0800 Subject: [PATCH 3/5] f --- lib/core/{httpclient4.js => httpclient_allow_h2.js} | 8 ++++---- lib/egg.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) rename lib/core/{httpclient4.js => httpclient_allow_h2.js} (90%) diff --git a/lib/core/httpclient4.js b/lib/core/httpclient_allow_h2.js similarity index 90% rename from lib/core/httpclient4.js rename to lib/core/httpclient_allow_h2.js index 2ec166a22e..66be1edf82 100644 --- a/lib/core/httpclient4.js +++ b/lib/core/httpclient_allow_h2.js @@ -2,7 +2,7 @@ const { HttpClient } = require('urllib4'); const ms = require('humanize-ms'); const SSRF_HTTPCLIENT = Symbol('SSRF_HTTPCLIENT'); -class HttpClient4 extends HttpClient { +class HttpClientAllowH2 extends HttpClient { constructor(app, options) { normalizeConfig(app); options = options || {}; @@ -13,7 +13,7 @@ class HttpClient4 extends HttpClient { super({ app, defaultArgs: options.request, - allowH2: options.allowH2, + allowH2: true, // use on egg-security ssrf // https://github.com/eggjs/egg-security/blob/master/lib/extend/safe_curl.js#L11 checkAddress: options.checkAddress, @@ -43,7 +43,7 @@ class HttpClient4 extends HttpClient { } else { this.app.logger.warn('[egg-security] please configure `config.security.ssrf` first'); } - this[SSRF_HTTPCLIENT] = new HttpClient4(this.app, { + this[SSRF_HTTPCLIENT] = new HttpClientAllowH2(this.app, { checkAddress: ssrfConfig.checkAddress, }); } @@ -58,4 +58,4 @@ function normalizeConfig(app) { } } -module.exports = HttpClient4; +module.exports = HttpClientAllowH2; diff --git a/lib/egg.js b/lib/egg.js index 33ed380152..65fcbc4f2f 100644 --- a/lib/egg.js +++ b/lib/egg.js @@ -20,11 +20,11 @@ const utils = require('./core/utils'); const BaseContextClass = require('./core/base_context_class'); const BaseHookClass = require('./core/base_hook_class'); -let HttpClient4 = HttpClientNext; +let HttpClientAllowH2 = HttpClientNext; const mainNodejsVersion = parseInt(process.versions.node.split('.')[0]); if (mainNodejsVersion >= 18) { // urllib@4 only works on Node.js >= 18 - HttpClient4 = require('./core/httpclient4'); + HttpClientAllowH2 = require('./core/httpclient_allow_h2'); } const HTTPCLIENT = Symbol('EggApplication#httpclient'); @@ -58,7 +58,7 @@ class EggApplication extends EggCore { this.ContextHttpClient = ContextHttpClient; this.HttpClient = HttpClient; this.HttpClientNext = HttpClientNext; - this.HttpClient4 = HttpClient4; + this.HttpClientAllowH2 = HttpClientAllowH2; this.loader.loadConfig(); @@ -301,7 +301,7 @@ class EggApplication extends EggCore { createHttpClient(options) { let httpClient; if (this.config.httpclient.allowH2) { - httpClient = new this.HttpClient4(this, options); + httpClient = new this.HttpClientAllowH2(this, options); } else if (this.config.httpclient.useHttpClientNext) { httpClient = new this.HttpClientNext(this, options); } else if (this.config.httpclient.enableDNSCache) { From f0964091ada78bad5cea8a4d80cf3cbb8310d0c8 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 16 Sep 2024 08:33:59 +0800 Subject: [PATCH 4/5] f --- test/fixtures/apps/httpclient-allowH2/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/apps/httpclient-allowH2/app.js b/test/fixtures/apps/httpclient-allowH2/app.js index 5af2297350..adf1121077 100644 --- a/test/fixtures/apps/httpclient-allowH2/app.js +++ b/test/fixtures/apps/httpclient-allowH2/app.js @@ -1,7 +1,7 @@ const assert = require('assert'); module.exports = app => { - class CustomHttpClient extends app.HttpClient4 { + class CustomHttpClient extends app.HttpClientAllowH2 { request(url, opt) { return new Promise(resolve => { assert(/^http/.test(url), 'url should start with http, but got ' + url); @@ -15,5 +15,5 @@ module.exports = app => { return this.request(url, opt); } } - app.HttpClient4 = CustomHttpClient; + app.HttpClientAllowH2 = CustomHttpClient; }; From d353b30ae9ebe036fd05c128e3491afafca83b58 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 16 Sep 2024 09:57:16 +0800 Subject: [PATCH 5/5] f --- lib/core/httpclient_allow_h2.js | 61 -------------------- lib/core/httpclient_next.js | 11 +++- lib/egg.js | 12 +--- test/fixtures/apps/httpclient-allowH2/app.js | 18 +++--- test/lib/core/httpclient.test.js | 7 ++- 5 files changed, 23 insertions(+), 86 deletions(-) delete mode 100644 lib/core/httpclient_allow_h2.js diff --git a/lib/core/httpclient_allow_h2.js b/lib/core/httpclient_allow_h2.js deleted file mode 100644 index 66be1edf82..0000000000 --- a/lib/core/httpclient_allow_h2.js +++ /dev/null @@ -1,61 +0,0 @@ -const { HttpClient } = require('urllib4'); -const ms = require('humanize-ms'); -const SSRF_HTTPCLIENT = Symbol('SSRF_HTTPCLIENT'); - -class HttpClientAllowH2 extends HttpClient { - constructor(app, options) { - normalizeConfig(app); - options = options || {}; - options = { - ...app.config.httpclient, - ...options, - }; - super({ - app, - defaultArgs: options.request, - allowH2: true, - // use on egg-security ssrf - // https://github.com/eggjs/egg-security/blob/master/lib/extend/safe_curl.js#L11 - checkAddress: options.checkAddress, - }); - this.app = app; - } - - async request(url, options) { - options = options || {}; - if (options.ctx && options.ctx.tracer) { - options.tracer = options.ctx.tracer; - } else { - options.tracer = options.tracer || this.app.tracer; - } - return await super.request(url, options); - } - - async curl(...args) { - return await this.request(...args); - } - - async safeCurl(url, options = {}) { - if (!this[SSRF_HTTPCLIENT]) { - const ssrfConfig = this.app.config.security.ssrf; - if (ssrfConfig?.checkAddress) { - options.checkAddress = ssrfConfig.checkAddress; - } else { - this.app.logger.warn('[egg-security] please configure `config.security.ssrf` first'); - } - this[SSRF_HTTPCLIENT] = new HttpClientAllowH2(this.app, { - checkAddress: ssrfConfig.checkAddress, - }); - } - return await this[SSRF_HTTPCLIENT].request(url, options); - } -} - -function normalizeConfig(app) { - const config = app.config.httpclient; - if (typeof config.request.timeout === 'string') { - config.request.timeout = ms(config.request.timeout); - } -} - -module.exports = HttpClientAllowH2; diff --git a/lib/core/httpclient_next.js b/lib/core/httpclient_next.js index 7d0fc4afea..0d0d7e48d8 100644 --- a/lib/core/httpclient_next.js +++ b/lib/core/httpclient_next.js @@ -1,7 +1,16 @@ -const { HttpClient } = require('urllib-next'); const ms = require('humanize-ms'); + const SSRF_HTTPCLIENT = Symbol('SSRF_HTTPCLIENT'); +const mainNodejsVersion = parseInt(process.versions.node.split('.')[0]); +let HttpClient; +if (mainNodejsVersion >= 18) { + // urllib@4 only works on Node.js >= 18 + HttpClient = require('urllib4').HttpClient; +} else { + HttpClient = require('urllib-next').HttpClient; +} + class HttpClientNext extends HttpClient { constructor(app, options) { normalizeConfig(app); diff --git a/lib/egg.js b/lib/egg.js index 65fcbc4f2f..8c1b4e9064 100644 --- a/lib/egg.js +++ b/lib/egg.js @@ -20,13 +20,6 @@ const utils = require('./core/utils'); const BaseContextClass = require('./core/base_context_class'); const BaseHookClass = require('./core/base_hook_class'); -let HttpClientAllowH2 = HttpClientNext; -const mainNodejsVersion = parseInt(process.versions.node.split('.')[0]); -if (mainNodejsVersion >= 18) { - // urllib@4 only works on Node.js >= 18 - HttpClientAllowH2 = require('./core/httpclient_allow_h2'); -} - const HTTPCLIENT = Symbol('EggApplication#httpclient'); const LOGGERS = Symbol('EggApplication#loggers'); const EGG_PATH = Symbol.for('egg#eggPath'); @@ -58,7 +51,6 @@ class EggApplication extends EggCore { this.ContextHttpClient = ContextHttpClient; this.HttpClient = HttpClient; this.HttpClientNext = HttpClientNext; - this.HttpClientAllowH2 = HttpClientAllowH2; this.loader.loadConfig(); @@ -300,9 +292,7 @@ class EggApplication extends EggCore { */ createHttpClient(options) { let httpClient; - if (this.config.httpclient.allowH2) { - httpClient = new this.HttpClientAllowH2(this, options); - } else if (this.config.httpclient.useHttpClientNext) { + if (this.config.httpclient.useHttpClientNext || this.config.httpclient.allowH2) { httpClient = new this.HttpClientNext(this, options); } else if (this.config.httpclient.enableDNSCache) { httpClient = new DNSCacheHttpClient(this, options); diff --git a/test/fixtures/apps/httpclient-allowH2/app.js b/test/fixtures/apps/httpclient-allowH2/app.js index adf1121077..b3d7873ba9 100644 --- a/test/fixtures/apps/httpclient-allowH2/app.js +++ b/test/fixtures/apps/httpclient-allowH2/app.js @@ -1,19 +1,15 @@ const assert = require('assert'); module.exports = app => { - class CustomHttpClient extends app.HttpClientAllowH2 { - request(url, opt) { - return new Promise(resolve => { - assert(/^http/.test(url), 'url should start with http, but got ' + url); - resolve(); - }).then(() => { - return super.request(url, opt); - }); + class CustomHttpClient extends app.HttpClientNext { + async request(url, opt) { + assert(/^http/.test(url), 'url should start with http, but got ' + url); + return await super.request(url, opt); } - curl(url, opt) { - return this.request(url, opt); + async curl(url, opt) { + return await this.request(url, opt); } } - app.HttpClientAllowH2 = CustomHttpClient; + app.HttpClientNext = CustomHttpClient; }; diff --git a/test/lib/core/httpclient.test.js b/test/lib/core/httpclient.test.js index f0ad78d222..09f3b6f258 100644 --- a/test/lib/core/httpclient.test.js +++ b/test/lib/core/httpclient.test.js @@ -310,12 +310,15 @@ describe('test/lib/core/httpclient.test.js', () => { after(() => app.close()); it('should work on http2', async () => { - const res = await app.httpclient.request(url); + const res = await app.httpclient.request(url, { + timeout: 5000, + }); assert.equal(res.status, 200); assert.equal(res.data.toString(), 'GET /'); // assert.equal(sensitiveHeaders in res.headers, false); const res2 = await app.httpclient.request('https://registry.npmmirror.com/urllib/latest', { dataType: 'json', + timeout: 5000, }); assert.equal(res2.status, 200); assert.equal(res2.data.name, 'urllib'); @@ -327,7 +330,7 @@ describe('test/lib/core/httpclient.test.js', () => { await app.httpclient.curl(`${url}/timeout`); }, err => { assert.equal(err.name, 'HttpClientRequestTimeoutError'); - assert(err.message.includes('Request timeout for 99 ms')); + assert.match(err.message, /timeout for 99 ms/); return true; }); });