From 189c478048d820b7b1a6ba6e8bce3444604876ff Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Wed, 10 Nov 2021 18:00:32 +0800 Subject: [PATCH] feat: handle ENETUNREACH error on httpclient (#4792) --- .github/workflows/nodejs.yml | 2 +- .travis.yml | 25 ------------------ .../zh-cn/faq/httpclient_ENETUNREACH.md | 6 +++++ lib/core/httpclient.js | 15 ++++++++++- package.json | 1 + test/lib/core/httpclient.test.js | 26 +++++++++++++++++++ 6 files changed, 48 insertions(+), 27 deletions(-) delete mode 100644 .travis.yml create mode 100644 docs/source/zh-cn/faq/httpclient_ENETUNREACH.md diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index dc34e1ce1f..36c1a25a3b 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -13,7 +13,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, macOS-latest, windows-latest ] - node-version: [ 8, 10, 12, 14 ] + node-version: [ 8, 10, 12, 14, 16 ] steps: - name: Checkout Git Source uses: actions/checkout@master diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f6f925c70a..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -sudo: false -cache: - npm: false -os: - - linux - - osx -language: node_js -node_js: - - '8' - - '10' - - '12' - - '14' -before_install: - - npm install -g npminstall -install: - - npminstall - - npminstall codecov -script: - - npm run ci -after_script: - - codecov - - test $TRAVIS_NODE_VERSION = 8 && travis_wait scripts/doc_travis.sh -env: - global: - - ENCRYPTION_LABEL: a62186272189 diff --git a/docs/source/zh-cn/faq/httpclient_ENETUNREACH.md b/docs/source/zh-cn/faq/httpclient_ENETUNREACH.md new file mode 100644 index 0000000000..e9438517ef --- /dev/null +++ b/docs/source/zh-cn/faq/httpclient_ENETUNREACH.md @@ -0,0 +1,6 @@ +# connect ENETUNREACH 异常 + +ENETUNREACH 的全称是 Network unreachable,网络不可达。 +一般是请求的域名解析出来的网络地址不可用,需要检查你的运行环境网络是否可用。 +如果在企业内部,很有可能受网络限制不允许对外网络互联,可以联系对应的网络工程师排查。 + diff --git a/lib/core/httpclient.js b/lib/core/httpclient.js index 9151ce6fae..cf0652f4ad 100644 --- a/lib/core/httpclient.js +++ b/lib/core/httpclient.js @@ -4,6 +4,13 @@ const Agent = require('agentkeepalive'); const HttpsAgent = require('agentkeepalive').HttpsAgent; const urllib = require('urllib'); const ms = require('humanize-ms'); +const { FrameworkBaseError } = require('egg-errors'); + +class HttpClientError extends FrameworkBaseError { + get module() { + return 'httpclient'; + } +} class HttpClient extends urllib.HttpClient2 { constructor(app) { @@ -42,7 +49,13 @@ class HttpClient extends urllib.HttpClient2 { } // the Promise style - return super.request(url, args); + return super.request(url, args) + .catch(err => { + if (err.code === 'ENETUNREACH') { + throw HttpClientError.create(err.message, err.code); + } + throw err; + }); } curl(url, args, callback) { diff --git a/package.json b/package.json index a3636997a0..696253df2d 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "egg-cookies": "^2.3.0", "egg-core": "^4.18.0", "egg-development": "^2.4.2", + "egg-errors": "^2.3.0", "egg-i18n": "^2.0.0", "egg-jsonp": "^2.0.0", "egg-logger": "^2.3.2", diff --git a/test/lib/core/httpclient.test.js b/test/lib/core/httpclient.test.js index 8a13273202..6e4e5fddd5 100644 --- a/test/lib/core/httpclient.test.js +++ b/test/lib/core/httpclient.test.js @@ -2,6 +2,7 @@ const assert = require('assert'); const mm = require('egg-mock'); +const urllib = require('urllib'); const Httpclient = require('../../../lib/core/httpclient'); const utils = require('../../utils'); @@ -87,6 +88,31 @@ describe('test/lib/core/httpclient.test.js', () => { await client.requestThunk(url, args); }); + it('should mock ENETUNREACH error', async () => { + mm(urllib.HttpClient2.prototype, 'request', () => { + const err = new Error('connect ENETUNREACH 1.1.1.1:80 - Local (127.0.0.1)'); + err.code = 'ENETUNREACH'; + return Promise.reject(err); + }); + await assert.rejects(async () => { + await client.request(url); + }, err => { + assert(err.name === 'HttpClientError'); + assert(err.code === 'httpclient_ENETUNREACH'); + assert(err.message === 'connect ENETUNREACH 1.1.1.1:80 - Local (127.0.0.1) [https://eggjs.org/zh-cn/faq/httpclient_ENETUNREACH]'); + return true; + }); + }); + + it('should handle timeout error', async () => { + await assert.rejects(async () => { + await client.request(url + '/timeout', { timeout: 100 }); + }, err => { + assert(err.name === 'ResponseTimeoutError'); + return true; + }); + }); + describe('httpclient.httpAgent.timeout < 30000', () => { let app; before(() => {