Skip to content

Commit

Permalink
feat: support allowH2 on urllib@4 (#5357)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 authored Sep 16, 2024
1 parent 550a4f1 commit 46d3fb2
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 88 deletions.
4 changes: 2 additions & 2 deletions config/config.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 10 additions & 1 deletion lib/core/httpclient_next.js
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
2 changes: 1 addition & 1 deletion lib/egg.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class EggApplication extends EggCore {
*/
createHttpClient(options) {
let httpClient;
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);
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand All @@ -77,19 +78,16 @@
"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",
"koa-static": "^5.0.0",
"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",
Expand Down
41 changes: 0 additions & 41 deletions test/doc.test.js

This file was deleted.

15 changes: 15 additions & 0 deletions test/fixtures/apps/httpclient-allowH2/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const assert = require('assert');

module.exports = app => {
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);
}

async curl(url, opt) {
return await this.request(url, opt);
}
}
app.HttpClientNext = CustomHttpClient;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
exports.httpclient = {
useHttpClientNext: true,
allowH2: true,
request: {
timeout: 99,
},
};
3 changes: 3 additions & 0 deletions test/fixtures/apps/httpclient-allowH2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "httpclient-allowH2"
}
21 changes: 0 additions & 21 deletions test/fixtures/apps/httpclient-http2/app.js

This file was deleted.

3 changes: 0 additions & 3 deletions test/fixtures/apps/httpclient-http2/package.json

This file was deleted.

4 changes: 2 additions & 2 deletions test/fixtures/apps/httpclient-tracer/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
Expand Down
57 changes: 45 additions & 12 deletions test/lib/core/httpclient.test.js
Original file line number Diff line number Diff line change
@@ -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');
Expand Down Expand Up @@ -305,30 +304,64 @@ 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());

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);
// 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');
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.match(err.message, /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;
});
});
});

Expand Down Expand Up @@ -618,13 +651,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,
});
Expand Down

0 comments on commit 46d3fb2

Please sign in to comment.